%PDF- %PDF-
Direktori : /lib/python3/dist-packages/softwareproperties/gtk/ |
Current File : //lib/python3/dist-packages/softwareproperties/gtk/UbuntuProPage.py |
# # Copyright (c) 2021 Canonical Ltd. # # 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 # USA import dbus import os from gettext import gettext as _ import gi gi.require_version("Gtk", "3.0") from gi.repository import GdkPixbuf, Gio, Gtk from softwareproperties.gtk.utils import current_distro, is_dark_theme from .DialogUaAttach import DialogUaAttach from .DialogUaDetach import DialogUaDetach from .DialogUaFipsEnable import DialogUaFipsEnable class UaService: def __init__(self, bus_object, name, entitled, status): self.bus_object = bus_object self.name = name self.entitled = entitled self.status = status self.request_in_progress = False class UbuntuProPage(object): def __init__(self, parent): self._parent = parent self.stack_ua_attach = parent.stack_ua_attach self.box_ua_attached = parent.box_ua_attached self.box_ua_unattached = parent.box_ua_unattached self.stack_ua_main = parent.stack_ua_main self.box_ua_options = parent.box_ua_options self.box_ua_fips_setup = parent.box_ua_fips_setup self.switch_ua_esm_infra = parent.switch_ua_esm_infra self.label_ua_esm_infra = parent.label_ua_esm_infra self.label_ua_esm_infra_error = parent.label_ua_esm_infra_error self.label_ua_esm_infra_error_messages = { "enable": _("Could not enable ESM Infra. Please try again."), "disable": _("Could not disable ESM Infra. Please try again."), } self.switch_ua_esm_apps = parent.switch_ua_esm_apps self.label_ua_esm_apps = parent.label_ua_esm_apps self.label_ua_esm_apps_error = parent.label_ua_esm_apps_error self.label_ua_esm_apps_error_messages = { "enable": _("Could not enable ESM Apps. Please try again."), "disable": _("Could not disable ESM Apps. Please try again."), } self.switch_ua_livepatch = parent.switch_ua_livepatch self.checkbutton_livepatch_topbar = parent.checkbutton_livepatch_topbar self.label_ua_livepatch = parent.label_ua_livepatch self.label_ua_livepatch_error = parent.label_ua_livepatch_error self.label_ua_livepatch_error_messages = { "enable": _("Could not enable Livepatch. Please try again."), "disable": _("Could not disable Livepatch. Please try again."), } self.button_ua_fips = parent.button_ua_fips self.label_ua_fips_status = parent.label_ua_fips_status self.label_ua_fips_description = parent.label_ua_fips_description self.button_ua_usg = parent.button_ua_usg self.label_ua_usg_button = parent.label_ua_usg_button self.label_ua_usg_status = parent.label_ua_usg_status self.label_ua_usg_description = parent.label_ua_usg_description if is_dark_theme(self.stack_ua_attach): ubuntu_pro_logo = GdkPixbuf.Pixbuf.new_from_file_at_scale(os.path.join(parent.datadir, 'ubuntu-pro-logo-dark.svg'), -1, 50, True) else: ubuntu_pro_logo = GdkPixbuf.Pixbuf.new_from_file_at_scale(os.path.join(parent.datadir, 'ubuntu-pro-logo.svg'), -1, 50, True) parent.image_ubuntu_pro_logo.set_from_pixbuf(ubuntu_pro_logo) # Display the tab on init which is only on LTS series self.stack_ua_main.set_visible(True) parent.button_ua_attach.connect('clicked', self.on_button_ua_attach_clicked) parent.button_ua_detach.connect('clicked', self.on_button_ua_detach_clicked) self.on_ua_esm_infra_changed_handler = self.switch_ua_esm_infra.connect('notify::active', self.on_ua_esm_infra_changed) self.on_ua_esm_apps_changed_handler = self.switch_ua_esm_apps.connect('notify::active', self.on_ua_esm_apps_changed) self.on_ua_livepatch_changed_handler = self.switch_ua_livepatch.connect('notify::active', self.on_ua_livepatch_changed) parent.button_ua_fips.connect('clicked', self.on_button_ua_fips_clicked) parent.button_ua_usg.connect('clicked', self.on_button_ua_usg_clicked) parent.expander_compliance_and_hardening.connect('notify::expanded', self.on_compliance_and_hardening_expand_changed) # Set date dependent labels distro = current_distro() if distro.eol_esm is not None: eol_year = distro.eol_esm.year self.label_ua_esm_infra.set_markup(_('<b>ESM Infra</b> provides security updates for over 2,300 Ubuntu Main packages until %d.') % eol_year) self.label_ua_esm_apps.set_markup(_('<b>ESM Apps</b>; provides security updates for over 23,000 Ubuntu Universe packages until %d.') % eol_year) else: self.label_ua_esm_infra.set_markup(_('<b>ESM Infra</b> provides security updates for over 2,300 Ubuntu Main packages.')) self.label_ua_esm_apps.set_markup(_('<b>ESM Apps</b>; provides security updates for over 23,000 Ubuntu Universe packages.')) self.update_notifier_settings = None source = Gio.SettingsSchemaSource.get_default() if source is not None: schema = source.lookup('com.ubuntu.update-notifier', True) if schema is not None: settings = Gio.Settings.new('com.ubuntu.update-notifier') if schema.has_key('show-livepatch-status-icon'): self.update_notifier_settings = settings if self.update_notifier_settings is not None: self.on_checkbutton_livepatch_topbar_toggled_handler = self.checkbutton_livepatch_topbar.connect('toggled', self.on_checkbutton_livepatch_topbar_toggled) self.on_update_notifier_settings_changed_handler = self.update_notifier_settings.connect('changed::show-livepatch-status-icon', self.on_update_notifier_settings_changed) self.on_update_notifier_settings_changed(self.update_notifier_settings, 'show-livepatch-status-icon') bus = dbus.SystemBus() self.ua_object = bus.get_object('com.canonical.UbuntuAdvantage', '/com/canonical/UbuntuAdvantage/Manager') # Monitor services self.attached = False self.services = {} def on_interfaces_added(path, interfaces_and_properties): if path == '/com/canonical/UbuntuAdvantage/Manager': self.attached = interfaces_and_properties['com.canonical.UbuntuAdvantage.Manager']['Attached'] elif path.startswith('/com/canonical/UbuntuAdvantage/Services/'): properties = interfaces_and_properties.get('com.canonical.UbuntuAdvantage.Service') bus_object = bus.get_object('com.canonical.UbuntuAdvantage', path) self.services[path] = UaService(bus_object, properties['Name'], properties['Entitled'], properties['Status']) self.update_status() def on_interfaces_removed(path, interfaces): if 'com.canonical.UbuntuAdvantage.Service' in interfaces: self.services.pop(path) self.update_status() def on_properties_changed(interface, changed_properties, invalidated_properties, path): def get_property(properties, name, default): value = properties.get(name) if value is None: value = default return value if path == '/com/canonical/UbuntuAdvantage/Manager' and interface == 'com.canonical.UbuntuAdvantage.Manager': self.attached = get_property(changed_properties, 'Attached', self.attached) elif path.startswith('/com/canonical/UbuntuAdvantage/Services/') and interface == 'com.canonical.UbuntuAdvantage.Service': service = self.services[path] service.entitled = get_property(changed_properties, 'Entitled', service.entitled) service.status = get_property(changed_properties, 'Status', service.status) self.update_status() object_manager_object = bus.get_object('com.canonical.UbuntuAdvantage', '/') object_manager_object.connect_to_signal('InterfacesAdded', on_interfaces_added, dbus_interface='org.freedesktop.DBus.ObjectManager') object_manager_object.connect_to_signal('InterfacesRemoved', on_interfaces_removed, dbus_interface='org.freedesktop.DBus.ObjectManager') bus.add_signal_receiver(on_properties_changed, bus_name='com.canonical.UbuntuAdvantage', signal_name='PropertiesChanged', dbus_interface='org.freedesktop.DBus.Properties', path_keyword='path') objects = object_manager_object.GetManagedObjects(dbus_interface='org.freedesktop.DBus.ObjectManager') for path in objects: on_interfaces_added(path, objects[path]) def get_service(self, name): for service in self.services.values(): if service.name == name: return service return None def update_status(self): if self.attached: self.stack_ua_attach.set_visible_child(self.box_ua_attached) else: self.stack_ua_attach.set_visible_child(self.box_ua_unattached) def entitled_to_service(service): return service is not None and service.entitled == 'yes' def service_request_in_progress(service): return service is not None and service.request_in_progress def service_is_enabled(service): return service is not None and service.status == 'enabled' def update_switch(switch, service, handler): if service is not None and service.request_in_progress: return switch.handler_block(handler) switch.set_active(service_is_enabled(service)) switch.handler_unblock(handler) esm_infra_service = self.get_service('esm-infra') for widget in [self.switch_ua_esm_infra, self.label_ua_esm_infra, self.label_ua_esm_infra_error]: widget.set_sensitive(entitled_to_service(esm_infra_service) and not service_request_in_progress(esm_infra_service)) update_switch(self.switch_ua_esm_infra, esm_infra_service, self.on_ua_esm_infra_changed_handler) esm_apps_service = self.get_service('esm-apps') for widget in [self.switch_ua_esm_apps, self.label_ua_esm_apps, self.label_ua_esm_apps_error]: widget.set_sensitive(entitled_to_service(esm_apps_service) and not service_request_in_progress(esm_apps_service)) update_switch(self.switch_ua_esm_apps, esm_apps_service, self.on_ua_esm_apps_changed_handler) livepatch_service = self.get_service('livepatch') for widget in [self.switch_ua_livepatch, self.label_ua_livepatch, self.label_ua_livepatch_error]: widget.set_sensitive(entitled_to_service(livepatch_service) and not service_request_in_progress(livepatch_service)) update_switch(self.switch_ua_livepatch, livepatch_service, self.on_ua_livepatch_changed_handler) self.checkbutton_livepatch_topbar.set_sensitive(self.update_notifier_settings is not None and self.switch_ua_livepatch.get_active()) fips_service = self.get_service('fips') fips_updates_service = self.get_service('fips-updates') fips_in_progress = service_request_in_progress(fips_service) or service_request_in_progress(fips_updates_service) self.button_ua_fips.set_sensitive(entitled_to_service(fips_service) and not fips_in_progress) if fips_in_progress: self.stack_ua_main.set_visible_child(self.box_ua_fips_setup) else: self.stack_ua_main.set_visible_child(self.box_ua_options) usg_service = self.get_service('usg') if not service_request_in_progress(usg_service): if service_is_enabled(usg_service): self.label_ua_usg_button.set_label(_('Disable _USG')) else: self.label_ua_usg_button.set_label(_('Enable _USG')) self.button_ua_usg.set_sensitive(entitled_to_service(usg_service) and not service_request_in_progress(usg_service)) def on_button_ua_attach_clicked(self, button): dialog = DialogUaAttach(self._parent.window_main, self._parent.datadir, self.ua_object) dialog.run() def on_button_ua_detach_clicked(self, button): dialog = DialogUaDetach(self._parent.window_main, self._parent.datadir, self.ua_object) dialog.run() def set_service_enabled(self, service_name, enabled, error_label, error_label_messages): if error_label is not None: error_label.set_visible(False) service = self.get_service(service_name) if service is None: return def on_reply(): service.request_in_progress = False self.update_status() def on_error(error): print(error) if error_label is not None: error_label.set_visible(True) if enabled: error_label.set_label(error_label_messages["enable"]) else: error_label.set_label(error_label_messages["disable"]) service.request_in_progress = False self.update_status() if enabled: service.bus_object.Enable(reply_handler=on_reply, error_handler=on_error, dbus_interface='com.canonical.UbuntuAdvantage.Service', timeout=600) else: service.bus_object.Disable(reply_handler=on_reply, error_handler=on_error, dbus_interface='com.canonical.UbuntuAdvantage.Service', timeout=600) service.request_in_progress = True self.update_status() def on_ua_esm_infra_changed(self, switch, param): self.set_service_enabled('esm-infra', self.switch_ua_esm_infra.get_active(), self.label_ua_esm_infra_error, self.label_ua_esm_infra_error_messages) def on_ua_esm_apps_changed(self, switch, param): self.set_service_enabled('esm-apps', self.switch_ua_esm_apps.get_active(), self.label_ua_esm_apps_error, self.label_ua_esm_apps_error_messages) def on_ua_livepatch_changed(self, switch, param): self.set_service_enabled('livepatch', self.switch_ua_livepatch.get_active(), self.label_ua_livepatch_error, self.label_ua_livepatch_error_messages) def on_checkbutton_livepatch_topbar_toggled(self, button): self.update_notifier_settings.handler_block(self.on_update_notifier_settings_changed_handler) self.update_notifier_settings.set_boolean('show-livepatch-status-icon', self.checkbutton_livepatch_topbar.get_active()) self.update_notifier_settings.handler_unblock(self.on_update_notifier_settings_changed_handler) def on_update_notifier_settings_changed(self, settings, key): self.checkbutton_livepatch_topbar.handler_block(self.on_checkbutton_livepatch_topbar_toggled_handler) self.checkbutton_livepatch_topbar.set_active(self.update_notifier_settings.get_boolean('show-livepatch-status-icon')) self.checkbutton_livepatch_topbar.handler_unblock(self.on_checkbutton_livepatch_topbar_toggled_handler) def on_button_ua_fips_clicked(self, button): dialog = DialogUaFipsEnable(self._parent.window_main, self._parent.datadir, self.ua_object) service_name = dialog.run() if service_name is None: return dialog = Gtk.MessageDialog(parent=self._parent.window_main, flags=Gtk.DialogFlags.MODAL, type=Gtk.MessageType.QUESTION, message_format=None) dialog.add_button(_('No, go back'), Gtk.ResponseType.CANCEL) dialog.add_button(_('Enable FIPS'), Gtk.ResponseType.OK) dialog.set_markup(_('Enabling FIPS could take a few minutes. This action cannot be reversed. Are you sure you want to enable FIPS?')) result = dialog.run() dialog.destroy() if result != Gtk.ResponseType.OK: return self.set_service_enabled(service_name, True, None, None) def on_button_ua_usg_clicked(self, button): service = self.get_service('usg') is_enabled = service is not None and service.status == 'enabled' self.set_service_enabled('usg', not is_enabled, None, None) def on_compliance_and_hardening_expand_changed(self, widget, param): self._parent.window_main.resize(1, 1)