gnome-control-center/panels/firmware-security/cc-firmware-security-dialog.c
Kate Hsuan 82b6e2c7bb firmware-security: Tweak panel style
Fix the spacing issues of several widgets, including the status icon,
label, and subtitle in a expander row.

Fixes: https://gitlab.gnome.org/GNOME/gnome-control-center/-/issues/1999
Signed-off-by: Kate Hsuan <hpa@redhat.com>
2022-08-10 16:31:26 -03:00

429 lines
18 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/* cc-firmware-security-dialog.c
*
* Copyright (C) 2021 Red Hat, Inc
*
* 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/>.
*
* Author: Kate Hsuan <hpa@redhat.com>
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/
#include "config.h"
#include <glib/gi18n-lib.h>
#include "cc-firmware-security-panel.h"
#include "cc-firmware-security-dialog.h"
#include "cc-firmware-security-utils.h"
struct _CcFirmwareSecurityDialog
{
AdwWindow parent;
GtkWidget *dialog_hsi_circle_box;
GtkWidget *dialog_hsi_circle_number;
GtkWidget *hsi1_icon;
GtkWidget *hsi2_icon;
GtkWidget *hsi3_icon;
GtkWidget *hsi1_title;
GtkWidget *hsi2_title;
GtkWidget *hsi3_title;
GtkWidget *firmware_security_dialog_title_label;
GtkWidget *firmware_security_dialog_body_label;
GtkWidget *firmware_security_dialog_min_row;
GtkWidget *firmware_security_dialog_basic_row;
GtkWidget *firmware_security_dialog_extend_row;
GtkWidget *firmware_security_dialog_hsi1_pg;
GtkWidget *firmware_security_dialog_hsi2_pg;
GtkWidget *firmware_security_dialog_hsi3_pg;
GtkWidget *firmware_security_dialog_hsi_label;
AdwLeaflet *leaflet;
AdwWindowTitle *second_page_title;
gboolean is_created;
GHashTable *hsi1_dict;
GHashTable *hsi2_dict;
GHashTable *hsi3_dict;
GHashTable *hsi4_dict;
guint hsi_number;
};
G_DEFINE_TYPE (CcFirmwareSecurityDialog, cc_firmware_security_dialog, ADW_TYPE_WINDOW)
static void
set_dialog_item_layer1 (CcFirmwareSecurityDialog *self,
const int hsi_number,
const gchar *title,
const gchar *body)
{
g_autofree gchar *str = NULL;
g_autofree gchar *hsi_str = NULL;
/* TRANSLATORS: HSI stands for Host Security ID and device refers to the computer as a whole */
str = g_strdup_printf (_("Device conforms to HSI level %d"), self->hsi_number);
hsi_str = g_strdup_printf ("%u", self->hsi_number);
gtk_label_set_label (GTK_LABEL (self->dialog_hsi_circle_number), hsi_str);
gtk_image_set_from_icon_name (GTK_IMAGE (self->hsi1_icon), hsi_number >= 1 ? "emblem-ok" : "process-stop");
gtk_label_set_text (GTK_LABEL (self->hsi1_title), hsi_number >= 1 ? _("Passed") : _("Failed"));
gtk_image_set_from_icon_name (GTK_IMAGE (self->hsi2_icon), hsi_number >= 2 ? "emblem-ok" : "process-stop");
gtk_label_set_text (GTK_LABEL (self->hsi2_title), hsi_number >= 2 ? _("Passed") : _("Failed"));
gtk_image_set_from_icon_name (GTK_IMAGE (self->hsi3_icon), hsi_number >= 3 ? "emblem-ok" : "process-stop");
gtk_label_set_text (GTK_LABEL (self->hsi3_title), hsi_number >= 3 ? _("Passed") : _("Failed"));
gtk_widget_add_css_class (self->firmware_security_dialog_min_row, hsi_number >= 1 ? "success-hsi-icon" : "error-hsi-icon");
gtk_widget_add_css_class (self->firmware_security_dialog_min_row, hsi_number >= 1 ? "success-title" : "error-title");
gtk_widget_add_css_class (self->firmware_security_dialog_basic_row, hsi_number >= 2 ? "success-hsi-icon" : "error-hsi-icon");
gtk_widget_add_css_class (self->firmware_security_dialog_basic_row, hsi_number >= 2 ? "success-title" : "error-title");
gtk_widget_add_css_class (self->firmware_security_dialog_extend_row, hsi_number >= 3 ? "success-hsi-icon" : "error-hsi-icon");
gtk_widget_add_css_class (self->firmware_security_dialog_extend_row, hsi_number >= 3 ? "success-title" : "error-title");
switch (hsi_number)
{
case 0:
gtk_widget_add_css_class (self->dialog_hsi_circle_box, "level0");
gtk_widget_add_css_class (self->dialog_hsi_circle_number, "hsi0");
break;
case 1:
gtk_widget_add_css_class (self->dialog_hsi_circle_box, "level1");
gtk_widget_add_css_class (self->dialog_hsi_circle_number, "hsi1");
break;
case 2:
gtk_widget_add_css_class (self->dialog_hsi_circle_box, "level2");
gtk_widget_add_css_class (self->dialog_hsi_circle_number, "hsi2");
break;
case 3:
case 4:
gtk_widget_add_css_class (self->dialog_hsi_circle_box, "level3");
gtk_widget_add_css_class (self->dialog_hsi_circle_number, "hsi3");
break;
}
gtk_label_set_text (GTK_LABEL (self->firmware_security_dialog_title_label), title);
gtk_label_set_text (GTK_LABEL (self->firmware_security_dialog_body_label), body);
gtk_label_set_text (GTK_LABEL (self->firmware_security_dialog_hsi_label), str);
}
static void
update_dialog (CcFirmwareSecurityDialog *self)
{
switch (self->hsi_number)
{
case 0:
set_dialog_item_layer1 (self,
0,
_("Security Level 0"),
_("This device has no protection against hardware security issues. This could "
"be because of a hardware or firmware configuration issue. It is "
"recommended to contact your IT support provider."));
break;
case 1:
set_dialog_item_layer1 (self,
1,
_("Security Level 1"),
_("This device has minimal protection against hardware security issues. This "
"is the lowest device security level and only provides protection against "
"simple security threats."));
break;
case 2:
set_dialog_item_layer1 (self,
2,
_("Security Level 2"),
_("This device has basic protection against hardware security issues. This "
"provides protection against some common security threats."));
break;
case 3:
case 4:
set_dialog_item_layer1 (self,
3,
_("Security Level 3"),
_("This device has extended protection against hardware security issues. This "
"is the highest device security level and provides protection against "
"advanced security threats."));
break;
default:
set_dialog_item_layer1 (self,
0,
_("Error: unable to determine HSI level."),
_("Error: unable to determine Incorrect HSI level."));
}
}
static gchar *
fu_security_attr_get_description_for_dialog (FwupdSecurityAttr *attr)
{
GString *str = g_string_new (attr->description);
if (attr->flags & FWUPD_SECURITY_ATTR_FLAG_ACTION_CONTACT_OEM &&
attr->flags & FWUPD_SECURITY_ATTR_FLAG_ACTION_CONFIG_FW &&
attr->flags & FWUPD_SECURITY_ATTR_FLAG_ACTION_CONFIG_FW)
{
g_string_append_printf (str, "\n\n%s %s",
/* TRANSLATORS: hardware manufacturer as in OEM */
_("Contact your hardware manufacturer for help with security updates."),
/* TRANSLATORS: support technician as in someone with root */
_("It might be possible to resolve this issue in the devices UEFI "
"firmware settings, or by a support technician."));
}
else if (attr->flags & FWUPD_SECURITY_ATTR_FLAG_ACTION_CONTACT_OEM &&
attr->flags & FWUPD_SECURITY_ATTR_FLAG_ACTION_CONFIG_FW)
{
g_string_append_printf (str, "\n\n%s %s",
/* TRANSLATORS: hardware manufacturer as in OEM */
_("Contact your hardware manufacturer for help with security updates."),
_("It might be possible to resolve this issue in the devices UEFI firmware settings."));
}
else if (attr->flags & FWUPD_SECURITY_ATTR_FLAG_ACTION_CONTACT_OEM)
{
g_string_append_printf (str, "\n\n%s",
/* TRANSLATORS: hardware manufacturer as in OEM */
_("Contact your hardware manufacturer for help with security updates."));
}
else if (attr->flags & FWUPD_SECURITY_ATTR_FLAG_ACTION_CONFIG_FW)
{
g_string_append_printf (str, "\n\n%s",
_("It might be possible to resolve this issue in the devices UEFI firmware settings."));
}
else if (attr->flags & FWUPD_SECURITY_ATTR_FLAG_ACTION_CONFIG_OS)
{
g_string_append_printf (str, "\n\n%s",
/* TRANSLATORS: support technician as in someone with root */
_("It might be possible for a support technician to resolve this issue."));
}
return g_string_free (str, FALSE);
}
static GtkWidget *
hsi_create_pg_row (const gchar *icon_name,
const gchar *style,
FwupdSecurityAttr *attr)
{
GtkWidget *row;
GtkWidget *status_icon;
GtkWidget *status_label;
GtkWidget *actions_parent;
const gchar *result_str = NULL;
row = adw_expander_row_new ();
adw_preferences_row_set_title (ADW_PREFERENCES_ROW (row), attr->title);
result_str = fwupd_security_attr_result_to_string(attr->result);
if (result_str)
{
status_label = gtk_label_new (result_str);
if (firmware_security_attr_has_flag (attr, FWUPD_SECURITY_ATTR_FLAG_SUCCESS))
status_icon = gtk_image_new_from_icon_name ("emblem-ok");
else
status_icon = gtk_image_new_from_icon_name ("process-stop");
adw_expander_row_add_action (ADW_EXPANDER_ROW (row), status_label);
adw_expander_row_add_action (ADW_EXPANDER_ROW (row), status_icon);
gtk_widget_add_css_class (status_icon, "icon");
gtk_widget_add_css_class (status_label, "hsi_label");
actions_parent = gtk_widget_get_parent (status_icon);
gtk_box_set_spacing (GTK_BOX (actions_parent), 6);
gtk_widget_set_margin_end (actions_parent, 12);
}
if (attr->description != NULL)
{
GtkWidget *subrow = adw_action_row_new ();
g_autofree gchar *str = fu_security_attr_get_description_for_dialog (attr);
gtk_widget_add_css_class (subrow, "view");
adw_action_row_set_subtitle (ADW_ACTION_ROW (subrow), str);
adw_expander_row_add_row (ADW_EXPANDER_ROW (row), subrow);
gtk_widget_add_css_class (subrow, "security-description-row");
}
else
{
adw_expander_row_set_enable_expansion (ADW_EXPANDER_ROW (row), FALSE);
}
return row;
}
static void
update_hsi_listbox (CcFirmwareSecurityDialog *self,
const gint hsi_level)
{
g_autoptr (GList) hash_keys = NULL;
GHashTable *hsi_dict = NULL;
GtkWidget *pg_row;
GtkWidget *hsi_pg;
switch (hsi_level)
{
case 1:
hsi_dict = self->hsi1_dict;
hsi_pg = self->firmware_security_dialog_hsi1_pg;
break;
case 2:
hsi_dict = self->hsi2_dict;
hsi_pg = self->firmware_security_dialog_hsi2_pg;
break;
case 3:
hsi_dict = self->hsi3_dict;
hsi_pg = self->firmware_security_dialog_hsi3_pg;
break;
case 4:
hsi_dict = self->hsi4_dict;
hsi_pg = self->firmware_security_dialog_hsi3_pg;
break;
}
hash_keys = g_hash_table_get_keys (hsi_dict);
for (GList *item = g_list_first (hash_keys); item != NULL; item = g_list_next (item))
{
FwupdSecurityAttr *attr = g_hash_table_lookup (hsi_dict, item->data);
if (g_strcmp0 (attr->appstream_id, FWUPD_SECURITY_ATTR_ID_SUPPORTED_CPU) == 0)
continue;
if (attr->title == NULL)
continue;
if (firmware_security_attr_has_flag (attr, FWUPD_SECURITY_ATTR_FLAG_SUCCESS))
{
pg_row = hsi_create_pg_row ("emblem-ok", "color_green", attr);
gtk_widget_add_css_class (pg_row, "success-icon");
gtk_widget_add_css_class (pg_row, "success-title");
}
else
{
pg_row = hsi_create_pg_row ("process-stop", "color_dim", attr);
gtk_widget_add_css_class (pg_row, "error-icon");
gtk_widget_add_css_class (pg_row, "error-title");
}
adw_preferences_group_add (ADW_PREFERENCES_GROUP (hsi_pg), GTK_WIDGET (pg_row));
}
self->is_created = TRUE;
}
static void
on_hsi_clicked_cb (GtkWidget *widget,
CcFirmwareSecurityDialog *self)
{
adw_leaflet_navigate (self->leaflet, ADW_NAVIGATION_DIRECTION_FORWARD);
if (!self->is_created)
{
update_hsi_listbox (self, 1);
update_hsi_listbox (self, 2);
update_hsi_listbox (self, 3);
update_hsi_listbox (self, 4);
self->is_created = TRUE;
}
if (widget == self->firmware_security_dialog_min_row)
{
adw_window_title_set_title (self->second_page_title, _("Security Level 1"));
gtk_widget_set_visible (self->firmware_security_dialog_hsi1_pg, TRUE);
}
else if (widget == self->firmware_security_dialog_basic_row)
{
adw_window_title_set_title (self->second_page_title, _("Security Level 2"));
gtk_widget_set_visible (self->firmware_security_dialog_hsi2_pg, TRUE);
}
else if (widget == self->firmware_security_dialog_extend_row)
{
adw_window_title_set_title (self->second_page_title, _("Security Level 3"));
gtk_widget_set_visible (self->firmware_security_dialog_hsi3_pg, TRUE);
}
}
static void
on_fw_back_button_clicked_cb (GtkWidget *widget,
gpointer data)
{
CcFirmwareSecurityDialog *self = CC_FIRMWARE_SECURITY_DIALOG (data);
adw_leaflet_navigate (self->leaflet, ADW_NAVIGATION_DIRECTION_BACK);
gtk_widget_set_visible (self->firmware_security_dialog_hsi1_pg, FALSE);
gtk_widget_set_visible (self->firmware_security_dialog_hsi2_pg, FALSE);
gtk_widget_set_visible (self->firmware_security_dialog_hsi3_pg, FALSE);
}
static void
cc_firmware_security_dialog_class_init (CcFirmwareSecurityDialogClass *klass)
{
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/control-center/firmware-security/cc-firmware-security-dialog.ui");
gtk_widget_class_bind_template_child (widget_class, CcFirmwareSecurityDialog, dialog_hsi_circle_box);
gtk_widget_class_bind_template_child (widget_class, CcFirmwareSecurityDialog, dialog_hsi_circle_number);
gtk_widget_class_bind_template_child (widget_class, CcFirmwareSecurityDialog, hsi1_icon);
gtk_widget_class_bind_template_child (widget_class, CcFirmwareSecurityDialog, hsi2_icon);
gtk_widget_class_bind_template_child (widget_class, CcFirmwareSecurityDialog, hsi3_icon);
gtk_widget_class_bind_template_child (widget_class, CcFirmwareSecurityDialog, hsi1_title);
gtk_widget_class_bind_template_child (widget_class, CcFirmwareSecurityDialog, hsi2_title);
gtk_widget_class_bind_template_child (widget_class, CcFirmwareSecurityDialog, hsi3_title);
gtk_widget_class_bind_template_child (widget_class, CcFirmwareSecurityDialog, firmware_security_dialog_title_label);
gtk_widget_class_bind_template_child (widget_class, CcFirmwareSecurityDialog, firmware_security_dialog_body_label);
gtk_widget_class_bind_template_child (widget_class, CcFirmwareSecurityDialog, firmware_security_dialog_hsi_label);
gtk_widget_class_bind_template_child (widget_class, CcFirmwareSecurityDialog, firmware_security_dialog_min_row);
gtk_widget_class_bind_template_child (widget_class, CcFirmwareSecurityDialog, firmware_security_dialog_basic_row);
gtk_widget_class_bind_template_child (widget_class, CcFirmwareSecurityDialog, firmware_security_dialog_extend_row);
gtk_widget_class_bind_template_child (widget_class, CcFirmwareSecurityDialog, firmware_security_dialog_hsi1_pg);
gtk_widget_class_bind_template_child (widget_class, CcFirmwareSecurityDialog, firmware_security_dialog_hsi2_pg);
gtk_widget_class_bind_template_child (widget_class, CcFirmwareSecurityDialog, firmware_security_dialog_hsi3_pg);
gtk_widget_class_bind_template_child (widget_class, CcFirmwareSecurityDialog, leaflet);
gtk_widget_class_bind_template_child (widget_class, CcFirmwareSecurityDialog, second_page_title);
gtk_widget_class_bind_template_callback (widget_class, on_hsi_clicked_cb);
gtk_widget_class_bind_template_callback (widget_class, on_fw_back_button_clicked_cb);
}
static void
cc_firmware_security_dialog_init (CcFirmwareSecurityDialog *dialog)
{
gtk_widget_init_template (GTK_WIDGET (dialog));
load_custom_css ("/org/gnome/control-center/firmware-security/security-level.css");
}
GtkWidget *
cc_firmware_security_dialog_new (guint hsi_number,
GHashTable *hsi1_dict,
GHashTable *hsi2_dict,
GHashTable *hsi3_dict,
GHashTable *hsi4_dict)
{
CcFirmwareSecurityDialog *dialog;
dialog = g_object_new (CC_TYPE_FIRMWARE_SECURITY_DIALOG, NULL);
dialog->hsi_number = hsi_number;
dialog->is_created = FALSE;
dialog->hsi1_dict = hsi1_dict;
dialog->hsi2_dict = hsi2_dict;
dialog->hsi3_dict = hsi3_dict;
dialog->hsi4_dict = hsi4_dict;
update_dialog (dialog);
return GTK_WIDGET (dialog);
}