Commit 6ee4ba04 authored by segfault's avatar segfault

Greeter: Support loading settings from persistence (refs: #17136)

parent 267ed10e
......@@ -78,7 +78,7 @@ class GreeterApplication(object):
self.macspoof_setting = MacSpoofSetting()
# Initialize the settings
settings = GreeterSettingsCollection(
self.settings = GreeterSettingsCollection(
LanguageSettingUI(self.localisationsettings.language),
KeyboardSettingUI(self.localisationsettings.keyboard),
FormatsSettingUI(self.localisationsettings.formats),
......@@ -88,7 +88,7 @@ class GreeterApplication(object):
)
# Initialize main window
self.mainwindow = GreeterMainWindow(self, persistence, settings)
self.mainwindow = GreeterMainWindow(self, persistence, self.settings)
# Inhibit the session being marked as idle
self.inhibit_idle()
......@@ -97,6 +97,29 @@ class GreeterApplication(object):
"""Translate all windows to target language"""
TranslatableWindow.translate_all(lang)
def load_settings(self):
if self.localisationsettings.language.load():
self.settings["language"].selected_code = self.localisationsettings.language.value
self.settings["language"].apply()
if self.localisationsettings.formats.load():
self.settings["formats"].selected_code = self.localisationsettings.formats.value
self.settings["formats"].apply()
if self.localisationsettings.keyboard.load():
self.settings["keyboard"].selected_code = self.localisationsettings.keyboard.value
self.settings["keyboard"].apply()
if self.admin_setting.load():
self.settings["admin"].password = self.admin_setting.password
self.mainwindow.add_setting("admin")
if self.network_setting.load():
if self.network_setting.value != self.settings["network"].value:
self.settings["network"].value = self.network_setting.value
self.mainwindow.add_setting("network")
if self.macspoof_setting.load():
if self.settings["macspoof"].spoofing_enabled != self.macspoof_setting.value:
self.settings["macspoof"].spoofing_enabled = self.macspoof_setting.value
self.mainwindow.add_setting("macspoof")
def login(self):
"""Login GDM to the server"""
logging.debug("login called")
......@@ -120,9 +143,9 @@ class GreeterApplication(object):
def on_language_changed(self, locale_code: str):
"""Translate to the given locale"""
self.localisationsettings.formats.on_language_changed(locale_code) # XXX: notify
self.mainwindow.settings["formats"].update_value_label()
self.settings["formats"].update_value_label()
self.localisationsettings.keyboard.on_language_changed(locale_code) # XXX: notify
self.mainwindow.settings["keyboard"].update_value_label()
self.settings["keyboard"].update_value_label()
self.translate_to(locale_code)
self.mainwindow.current_language = localization.language_from_locale(locale_code)
......
......@@ -5,6 +5,7 @@ import logging
import pipes
import tailsgreeter.config
from tailsgreeter.settings.utils import read_settings, write_settings
class AdminSetting(object):
......@@ -12,23 +13,35 @@ class AdminSetting(object):
def __init__(self):
self.password = None
self.settings_file = tailsgreeter.config.admin_password_path
def apply_to_upcoming_session(self):
setting_file = tailsgreeter.config.admin_password_path
if self.password:
with open(setting_file, 'w') as f:
os.chmod(setting_file, 0o600)
f.write('TAILS_USER_PASSWORD=%s\n' % pipes.quote(self.password))
logging.debug('password written to %s', setting_file)
write_settings(self.settings_file, {
'TAILS_USER_PASSWORD': pipes.quote(self.password),
})
logging.debug('password written to %s', self.settings_file)
return
# Try to remove the password file
try:
os.unlink(setting_file)
logging.debug('removed %s', setting_file)
os.unlink(self.settings_file)
logging.debug('removed %s', self.settings_file)
except OSError:
# It's bad if the file exists and couldn't be removed, so we
# we raise the exception in that case (which prevents the login)
if os.path.exists(setting_file):
if os.path.exists(self.settings_file):
raise
def load(self) -> bool:
try:
settings = read_settings(self.settings_file)
except FileNotFoundError:
logging.debug("No persistent admin settings file found (path: %s)", self.settings_file)
return False
password = settings.get('TAILS_USER_PASSWORD')
if password:
self.password = password
logging.debug("Loaded admin password setting")
return True
......@@ -4,7 +4,7 @@ import os
import tailsgreeter.config
from tailsgreeter.settings.localization import LocalizationSetting, language_from_locale, country_from_locale
from tailsgreeter.settings.utils import write_settings
from tailsgreeter.settings.utils import read_settings, write_settings
gi.require_version('GObject', '2.0')
gi.require_version('GnomeDesktop', '3.0')
......@@ -17,14 +17,29 @@ class FormatsSetting(LocalizationSetting):
super().__init__()
self.value = 'en_US'
self.locales_per_country = self._make_locales_per_country_dict(language_codes)
self.settings_file = tailsgreeter.config.formats_setting_path
def apply_to_upcoming_session(self):
settings_file = tailsgreeter.config.formats_setting_path
write_settings(settings_file, {
write_settings(self.settings_file, {
'TAILS_FORMATS': self.get_value(),
'IS_DEFAULT': (not self.value_changed_by_user),
'IS_DEFAULT': str(not self.value_changed_by_user).lower(),
})
def load(self) -> bool:
try:
settings = read_settings(self.settings_file)
except FileNotFoundError:
logging.debug("No persistent formats settings file found (path: %s)", self.settings_file)
return False
formats = settings.get('TAILS_FORMATS')
if not formats:
return False
is_default = settings.get('IS_DEFAULT') == 'true'
self.set_value(formats, chosen_by_user=not is_default)
logging.debug("Loaded formats setting '%s' (is default: %s)", formats, is_default)
return True
def get_tree(self) -> Gtk.TreeStore:
treestore = Gtk.TreeStore(GObject.TYPE_STRING, # id
GObject.TYPE_STRING) # name
......
......@@ -4,7 +4,7 @@ import logging
import tailsgreeter.config
from tailsgreeter.settings.localization import LocalizationSetting, ln_iso639_tri, \
ln_iso639_2_T_to_B, language_from_locale, country_from_locale
from tailsgreeter.settings.utils import write_settings
from tailsgreeter.settings.utils import read_settings, write_settings
gi.require_version('Gio', '2.0')
gi.require_version('GLib', '2.0')
......@@ -20,6 +20,7 @@ class KeyboardSetting(LocalizationSetting):
super().__init__()
self.xkbinfo = GnomeDesktop.XkbInfo()
self.value = 'us'
self.settings_file = tailsgreeter.config.keyboard_setting_path
def apply_to_upcoming_session(self):
try:
......@@ -28,15 +29,35 @@ class KeyboardSetting(LocalizationSetting):
layout = self.get_value()
variant = ''
settings_file = tailsgreeter.config.keyboard_setting_path
write_settings(settings_file, {
write_settings(self.settings_file, {
# The default value from /etc/default/keyboard
'TAILS_XKBMODEL': 'pc105',
'TAILS_XKBLAYOUT': layout,
'TAILS_XKBVARIANT': variant,
'IS_DEFAULT': (not self.value_changed_by_user),
'IS_DEFAULT': str(not self.value_changed_by_user).lower(),
})
def load(self) -> bool:
try:
settings = read_settings(self.settings_file)
except FileNotFoundError:
logging.debug("No persistent keyboard settings file found (path: %s)", self.settings_file)
return False
keyboard_layout = settings.get('TAILS_XKBLAYOUT')
if not keyboard_layout:
return False
keyboard_variant = settings.get('TAILS_XKBVARIANT')
if keyboard_variant:
keyboard_layout += "+" + keyboard_variant
is_default = settings.get('IS_DEFAULT') == 'true'
self.set_value(keyboard_layout, chosen_by_user=not is_default)
logging.debug("Loaded keyboard setting '%s' (is default: %s)", keyboard_layout, is_default)
return True
def get_tree(self, layout_codes=None) -> Gtk.TreeStore:
if not layout_codes:
layout_codes = self.get_all()
......
......@@ -26,7 +26,7 @@ from typing import Callable
import tailsgreeter.config
from tailsgreeter.settings.localization import LocalizationSetting, \
language_from_locale, country_from_locale
from tailsgreeter.settings.utils import write_settings
from tailsgreeter.settings.utils import read_settings, write_settings
gi.require_version('GLib', '2.0')
gi.require_version('GObject', '2.0')
......@@ -43,18 +43,33 @@ class LanguageSetting(LocalizationSetting):
self.locales = locales
self.language_changed_cb = language_changed_cb
self._user_account = None
self.settings_file = tailsgreeter.config.language_setting_path
self.lang_codes = self._languages_from_locales(locales)
self.locales_per_language = self._make_language_to_locale_dict(locales)
self.language_names_per_language = self._make_language_to_language_name_dict(self.lang_codes)
def apply_to_upcoming_session(self):
settings_file = tailsgreeter.config.language_setting_path
write_settings(settings_file, {
write_settings(self.settings_file, {
'TAILS_LOCALE_NAME': self.get_value(),
'IS_DEFAULT': (not self.value_changed_by_user),
'IS_DEFAULT': str(not self.value_changed_by_user).lower(),
})
def load(self) -> bool:
try:
settings = read_settings(self.settings_file)
except FileNotFoundError:
logging.debug("No persistent language settings file found (path: %s)", self.settings_file)
return False
language = settings.get('TAILS_LOCALE_NAME')
if not language:
return False
is_default = settings.get('IS_DEFAULT') == 'true'
self.set_value(language, chosen_by_user=not is_default)
logging.debug("Loaded language setting '%s' (is default: %s)", language, is_default)
return True
def get_tree(self) -> Gtk.TreeStore:
treestore = Gtk.TreeStore(GObject.TYPE_STRING, # id
GObject.TYPE_STRING) # name
......
import os
import logging
import pipes
import tailsgreeter.config
from tailsgreeter.settings.utils import read_settings, write_settings
class MacSpoofSetting(object):
......@@ -10,10 +10,23 @@ class MacSpoofSetting(object):
def __init__(self):
self.value = True
self.settings_file = tailsgreeter.config.macspoof_setting_path
def apply_to_upcoming_session(self):
setting_file = tailsgreeter.config.macspoof_setting_path
with open(setting_file, 'w') as f:
os.chmod(setting_file, 0o600)
f.write("TAILS_MACSPOOF_ENABLED=%s\n" % pipes.quote(str(self.value)).lower())
logging.debug('macspoof setting written to %s', setting_file)
write_settings(self.settings_file, {
'TAILS_MACSPOOF_ENABLED': pipes.quote(str(self.value)).lower(),
})
logging.debug('macspoof setting written to %s', self.settings_file)
def load(self) -> bool:
try:
settings = read_settings(self.settings_file)
except FileNotFoundError:
logging.debug("No persistent macspoof settings file found (path: %s)", self.settings_file)
return False
value = settings.get('TAILS_MACSPOOF_ENABLED') == "true"
if value:
self.value = value
logging.debug("Loaded macspoof setting '%s'", value)
return True
import os
import logging
import pipes
import tailsgreeter.config
from tailsgreeter.settings.utils import read_settings, write_settings
class NetworkSetting(object):
......@@ -14,10 +14,23 @@ class NetworkSetting(object):
def __init__(self):
self.value = self.NETCONF_DIRECT
self.settings_file = tailsgreeter.config.network_setting_path
def apply_to_upcoming_session(self):
setting_file = tailsgreeter.config.network_setting_path
with open(setting_file, 'w') as f:
os.chmod(setting_file, 0o600)
f.write("TAILS_NETCONF=%s\n" % pipes.quote(self.value))
logging.debug('network setting written to %s', setting_file)
write_settings(self.settings_file, {
'TAILS_NETCONF': pipes.quote(self.value),
})
logging.debug('network setting written to %s', self.settings_file)
def load(self) -> bool:
try:
settings = read_settings(self.settings_file)
except FileNotFoundError:
logging.debug("No persistent network settings file found (path: %s)", self.settings_file)
return False
value = settings.get('TAILS_NETCONF')
if value:
self.value = value
logging.debug("Loaded network setting '%s'", value)
return True
......@@ -6,3 +6,17 @@ def write_settings(filename: str, settings: dict):
os.chmod(filename, 0o600)
for key, value in settings.items():
f.write('%s=%s\n' % (key, value))
def read_settings(filename: str) -> dict:
with open(filename) as f:
lines = f.readlines()
settings = dict()
for line in lines:
try:
key, value = line.split('=', 1)
except ValueError:
continue
settings[key] = value.rstrip()
return settings
......@@ -131,7 +131,7 @@ class GreeterMainWindow(Gtk.Window, TranslatableWindow):
self.listbox_settings.set_placeholder(self.label_settings_default)
# Persistent storage
self.persistent_storage = PersistentStorage(self.persistence_setting, builder)
self.persistent_storage = PersistentStorage(self.persistence_setting, greeter, builder)
# Add children to ApplicationWindow
self.add(self.box_main)
......@@ -176,31 +176,17 @@ class GreeterMainWindow(Gtk.Window, TranslatableWindow):
# Actions
def add_setting(self, id_=None):
def run_add_setting_dialog(self, id_=None):
response = self.dialog_add_setting.run(id_)
if response == Gtk.ResponseType.YES:
row = self.listbox_add_setting.get_selected_row()
id_ = self.settings.id_from_row(row)
setting = self.settings.additional_settings[id_]
# The setting used to be applied by the dialog itself, but there
# we don't know the response type in all cases. For example, we
# previously didn't apply the admin password in all cases if the
# "Add" button was clicked to close the dialog (#13447).
setting.apply()
setting.update_value_label()
self.listbox_add_setting.remove(row)
self.listbox_settings.add(row)
self.dialog_add_setting.set_visible(False)
self.dialog_add_setting.stack.remove(setting.box)
setting.build_popover()
self.listbox_settings.unselect_all()
if True not in [c.get_visible() for c in
self.listbox_add_setting.get_children()]:
self.toolbutton_settings_add.set_sensitive(False)
self.dialog_add_setting.set_visible(False)
self.add_setting(id_)
else:
old_details = self.dialog_add_setting.stack.get_child_by_name(
'setting-details')
......@@ -208,11 +194,24 @@ class GreeterMainWindow(Gtk.Window, TranslatableWindow):
self.dialog_add_setting.stack.remove(old_details)
self.dialog_add_setting.set_visible(False)
def add_setting(self, id_):
logging.debug("Adding setting '%s'", id_)
setting = self.settings.additional_settings[id_]
setting.apply()
setting.build_popover()
self.listbox_add_setting.remove(setting.listboxrow)
self.listbox_settings.add(setting.listboxrow)
self.listbox_settings.unselect_all()
if not self.listbox_add_setting.get_children():
self.toolbutton_settings_add.set_sensitive(False)
def edit_setting(self, id_):
if self.settings[id_].has_popover():
self.settings[id_].listboxrow.emit("activate")
else:
self.add_setting(id_)
self.run_add_setting_dialog(id_)
def show(self):
super().show()
......@@ -351,11 +350,11 @@ class GreeterMainWindow(Gtk.Window, TranslatableWindow):
setting.apply()
def cb_toolbutton_settings_add_clicked(self, user_data=None):
self.add_setting()
self.run_add_setting_dialog()
return False
def cb_toolbutton_settings_mnemonic_activate(self, widget, group_cycling):
self.add_setting()
self.run_add_setting_dialog()
return False
def cb_window_delete_event(self, widget, event, user_data=None):
......
......@@ -14,8 +14,9 @@ if TYPE_CHECKING:
class PersistentStorage(object):
def __init__(self, persistence_setting: "PersistenceSettings", builder):
def __init__(self, persistence_setting: "PersistenceSettings", greeter, builder):
self.persistence_setting = persistence_setting
self.greeter = greeter
self.box_storage = builder.get_object('box_storage')
self.box_storage_unlock = builder.get_object('box_storage_unlock')
......@@ -108,6 +109,7 @@ class PersistentStorage(object):
self.image_storage_state.set_visible(True)
self.box_storage_unlocked.set_visible(True)
self.button_start.set_sensitive(True)
self.greeter.load_settings()
def cb_checkbutton_storage_show_passphrase_toggled(self, widget):
self.entry_storage_passphrase.set_visibility(widget.get_active())
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment