Export the report metadata on the D-Bus interface

This allows the client to easily query metadata to upload with the report,
without exporting rarely used attributes as D-Bus properties on the interface.

It also allows us to add extra metadata values in the future without changing
the public API.
This commit is contained in:
Richard Hughes 2020-05-20 18:42:46 +01:00
parent 0c6efe2e04
commit 6ecc4ca144
7 changed files with 152 additions and 23 deletions

View File

@ -404,6 +404,71 @@ fwupd_client_get_host_security_attrs (FwupdClient *client, GCancellable *cancell
return fwupd_security_attr_array_from_variant (val);
}
static GHashTable *
fwupd_report_metadata_hash_from_variant (GVariant *value)
{
GHashTable *hash;
gsize sz;
g_autoptr(GVariant) untuple = NULL;
hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
untuple = g_variant_get_child_value (value, 0);
sz = g_variant_n_children (untuple);
for (guint i = 0; i < sz; i++) {
g_autoptr(GVariant) data = NULL;
const gchar *key = NULL;
const gchar *val = NULL;
data = g_variant_get_child_value (untuple, i);
g_variant_get (data, "{&s&s}", &key, &val);
g_hash_table_insert (hash, g_strdup (key), g_strdup (val));
}
return hash;
}
/**
* fwupd_client_get_report_metadata:
* @client: A #FwupdClient
* @cancellable: the #GCancellable, or %NULL
* @error: the #GError, or %NULL
*
* Gets all the report metadata from the daemon.
*
* Returns: (transfer container): attributes
*
* Since: 1.5.0
**/
GHashTable *
fwupd_client_get_report_metadata (FwupdClient *client,
GCancellable *cancellable,
GError **error)
{
FwupdClientPrivate *priv = GET_PRIVATE (client);
g_autoptr(GVariant) val = NULL;
g_return_val_if_fail (FWUPD_IS_CLIENT (client), NULL);
g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), NULL);
g_return_val_if_fail (error == NULL || *error == NULL, NULL);
/* connect */
if (!fwupd_client_connect (client, cancellable, error))
return NULL;
/* call into daemon */
val = g_dbus_proxy_call_sync (priv->proxy,
"GetReportMetadata",
NULL,
G_DBUS_CALL_FLAGS_NONE,
-1,
cancellable,
error);
if (val == NULL) {
if (error != NULL)
fwupd_client_fixup_dbus_error (*error);
return NULL;
}
return fwupd_report_metadata_hash_from_variant (val);
}
/**
* fwupd_client_get_devices:
* @client: A #FwupdClient

View File

@ -130,6 +130,9 @@ gboolean fwupd_client_modify_device (FwupdClient *client,
const gchar *value,
GCancellable *cancellable,
GError **error);
GHashTable *fwupd_client_get_report_metadata (FwupdClient *client,
GCancellable *cancellable,
GError **error);
FwupdStatus fwupd_client_get_status (FwupdClient *client);
gboolean fwupd_client_get_tainted (FwupdClient *client);
gboolean fwupd_client_get_daemon_interactive (FwupdClient *client);

View File

@ -451,6 +451,7 @@ LIBFWUPD_1.5.0 {
global:
fwupd_client_get_host_security_attrs;
fwupd_client_get_host_security_id;
fwupd_client_get_report_metadata;
fwupd_security_attr_add_flag;
fwupd_security_attr_add_obsolete;
fwupd_security_attr_array_from_variant;

View File

@ -1342,14 +1342,43 @@ fu_engine_get_boot_time (void)
return NULL;
}
static GHashTable *
fu_engine_get_report_metadata (FuEngine *self)
static gboolean
fu_engine_get_report_metadata_os_release (GHashTable *hash, GError **error)
{
g_autoptr(GHashTable) os_release = NULL;
struct {
const gchar *key;
const gchar *val;
} distro_kv[] = {
{ "ID", "DistroId" },
{ "VERSION_ID", "DistroVersion" },
{ "VARIANT_ID", "DistroVariant" },
{ NULL, NULL }
};
/* get all required os-release keys */
os_release = fwupd_get_os_release (error);
if (os_release == NULL)
return FALSE;
for (guint i = 0; distro_kv[i].key != NULL; i++) {
const gchar *tmp = g_hash_table_lookup (os_release, distro_kv[i].key);
if (tmp != NULL) {
g_hash_table_insert (hash,
g_strdup (distro_kv[i].val),
g_strdup (tmp));
}
}
return TRUE;
}
GHashTable *
fu_engine_get_report_metadata (FuEngine *self, GError **error)
{
GHashTable *hash;
gchar *btime;
#ifdef HAVE_UTSNAME_H
struct utsname name_tmp;
#endif
g_autoptr(GHashTable) hash = NULL;
g_autoptr(GList) compile_keys = g_hash_table_get_keys (self->compile_versions);
g_autoptr(GList) runtime_keys = g_hash_table_get_keys (self->runtime_versions);
@ -1369,6 +1398,8 @@ fu_engine_get_report_metadata (FuEngine *self)
g_strdup_printf ("RuntimeVersion(%s)", id),
g_strdup (version));
}
if (!fu_engine_get_report_metadata_os_release (hash, error))
return NULL;
/* kernel version is often important for debugging failures */
#ifdef HAVE_UTSNAME_H
@ -1385,7 +1416,7 @@ fu_engine_get_report_metadata (FuEngine *self)
if (btime != NULL)
g_hash_table_insert (hash, g_strdup ("BootTime"), btime);
return hash;
return g_steal_pointer (&hash);
}
/**
@ -1530,18 +1561,13 @@ static FwupdRelease *
fu_engine_create_release_metadata (FuEngine *self, FuPlugin *plugin, GError **error)
{
GPtrArray *metadata_sources;
const gchar *tmp;
g_autoptr(FwupdRelease) release = fwupd_release_new ();
g_autoptr(GHashTable) metadata_hash = NULL;
g_autoptr(GHashTable) os_release = NULL;
/* add release data from os-release */
os_release = fwupd_get_os_release (error);
if (os_release == NULL)
return NULL;
/* build the version metadata */
metadata_hash = fu_engine_get_report_metadata (self);
metadata_hash = fu_engine_get_report_metadata (self, error);
if (metadata_hash == NULL)
return NULL;
fwupd_release_add_metadata (release, metadata_hash);
fwupd_release_add_metadata (release, fu_plugin_get_report_metadata (plugin));
@ -1564,17 +1590,6 @@ fu_engine_create_release_metadata (FuEngine *self, FuPlugin *plugin, GError **er
fwupd_release_add_metadata (release,
fu_plugin_get_report_metadata (plugin_tmp));
}
/* add details from os-release as metadata */
tmp = g_hash_table_lookup (os_release, "ID");
if (tmp != NULL)
fwupd_release_add_metadata_item (release, "DistroId", tmp);
tmp = g_hash_table_lookup (os_release, "VERSION_ID");
if (tmp != NULL)
fwupd_release_add_metadata_item (release, "DistroVersion", tmp);
tmp = g_hash_table_lookup (os_release, "VARIANT_ID");
if (tmp != NULL)
fwupd_release_add_metadata_item (release, "DistroVariant", tmp);
return g_steal_pointer (&release);
}

View File

@ -85,6 +85,8 @@ FwupdDevice *fu_engine_get_results (FuEngine *self,
const gchar *device_id,
GError **error);
FuSecurityAttrs *fu_engine_get_host_security_attrs (FuEngine *self);
GHashTable *fu_engine_get_report_metadata (FuEngine *self,
GError **error);
gboolean fu_engine_clear_results (FuEngine *self,
const gchar *device_id,
GError **error);

View File

@ -858,6 +858,31 @@ fu_main_daemon_method_call (GDBusConnection *connection, const gchar *sender,
g_variant_new_tuple (&val, 1));
return;
}
if (g_strcmp0 (method_name, "GetReportMetadata") == 0) {
GHashTableIter iter;
GVariantBuilder builder;
const gchar *key;
const gchar *value;
g_autoptr(GHashTable) metadata = NULL;
metadata = fu_engine_get_report_metadata (priv->engine, &error);
if (metadata == NULL) {
g_dbus_method_invocation_return_gerror (invocation, error);
return;
}
g_variant_builder_init (&builder, G_VARIANT_TYPE ("a{ss}"));
g_hash_table_iter_init (&iter, metadata);
while (g_hash_table_iter_next (&iter,
(gpointer *) &key,
(gpointer *) &value)) {
g_variant_builder_add_value (&builder,
g_variant_new ("{ss}", key, value));
}
val = g_variant_builder_end (&builder);
g_dbus_method_invocation_return_value (invocation,
g_variant_new_tuple (&val, 1));
return;
}
if (g_strcmp0 (method_name, "SetApprovedFirmware") == 0) {
g_autofree gchar *checksums_str = NULL;
g_auto(GStrv) checksums = NULL;

View File

@ -271,6 +271,24 @@
</arg>
</method>
<!--***********************************************************-->
<method name='GetReportMetadata'>
<doc:doc>
<doc:description>
<doc:para>
Gets metadata to include with the firmware and security reports.
</doc:para>
</doc:description>
</doc:doc>
<arg type='a{ss}' name='attrs' direction='out'>
<doc:doc>
<doc:summary>
<doc:para>An array of string key values.</doc:para>
</doc:summary>
</doc:doc>
</arg>
</method>
<!--***********************************************************-->
<method name='Install'>
<doc:doc>