|
|
06f198 |
From f723ed1078e050c4d966d40b2aea74970c74279c Mon Sep 17 00:00:00 2001
|
|
|
06f198 |
From: Kalev Lember <klember@redhat.com>
|
|
|
06f198 |
Date: Thu, 27 Jun 2019 16:12:00 +0200
|
|
|
06f198 |
Subject: [PATCH 02/15] subman: Add InstalledProducts dbus property for g-c-c
|
|
|
06f198 |
|
|
|
06f198 |
---
|
|
|
06f198 |
plugins/subman/gsd-subscription-manager.c | 135 ++++++++++++++++++++++
|
|
|
06f198 |
1 file changed, 135 insertions(+)
|
|
|
06f198 |
|
|
|
06f198 |
diff --git a/plugins/subman/gsd-subscription-manager.c b/plugins/subman/gsd-subscription-manager.c
|
|
|
06f198 |
index 08b13fa6..a8c18a26 100644
|
|
|
06f198 |
--- a/plugins/subman/gsd-subscription-manager.c
|
|
|
06f198 |
+++ b/plugins/subman/gsd-subscription-manager.c
|
|
|
06f198 |
@@ -1,186 +1,304 @@
|
|
|
06f198 |
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
|
|
|
06f198 |
*
|
|
|
06f198 |
* Copyright (C) 2019 Richard Hughes <richard@hughsie.com>
|
|
|
06f198 |
+ * Copyright (C) 2019 Kalev Lember <klember@redhat.com>
|
|
|
06f198 |
*
|
|
|
06f198 |
* This program is free software; you can redistribute it and/or modify
|
|
|
06f198 |
* it under the terms of the GNU General Public License as published by
|
|
|
06f198 |
* the Free Software Foundation; either version 2 of the License, or
|
|
|
06f198 |
* (at your option) any later version.
|
|
|
06f198 |
*
|
|
|
06f198 |
* This program is distributed in the hope that it will be useful,
|
|
|
06f198 |
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
06f198 |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
06f198 |
* GNU General Public License for more details.
|
|
|
06f198 |
*
|
|
|
06f198 |
* You should have received a copy of the GNU General Public License
|
|
|
06f198 |
* along with this program; if not, see <http://www.gnu.org/licenses/>.
|
|
|
06f198 |
*
|
|
|
06f198 |
*/
|
|
|
06f198 |
|
|
|
06f198 |
#include "config.h"
|
|
|
06f198 |
|
|
|
06f198 |
#include <glib/gi18n.h>
|
|
|
06f198 |
#include <gdk/gdk.h>
|
|
|
06f198 |
#include <gtk/gtk.h>
|
|
|
06f198 |
#include <json-glib/json-glib.h>
|
|
|
06f198 |
#include <libnotify/notify.h>
|
|
|
06f198 |
|
|
|
06f198 |
#include "gnome-settings-profile.h"
|
|
|
06f198 |
#include "gsd-subman-common.h"
|
|
|
06f198 |
#include "gsd-subscription-manager.h"
|
|
|
06f198 |
|
|
|
06f198 |
#define GSD_DBUS_NAME "org.gnome.SettingsDaemon"
|
|
|
06f198 |
#define GSD_DBUS_PATH "/org/gnome/SettingsDaemon"
|
|
|
06f198 |
#define GSD_DBUS_BASE_INTERFACE "org.gnome.SettingsDaemon"
|
|
|
06f198 |
|
|
|
06f198 |
#define GSD_SUBSCRIPTION_DBUS_NAME GSD_DBUS_NAME ".Subscription"
|
|
|
06f198 |
#define GSD_SUBSCRIPTION_DBUS_PATH GSD_DBUS_PATH "/Subscription"
|
|
|
06f198 |
#define GSD_SUBSCRIPTION_DBUS_INTERFACE GSD_DBUS_BASE_INTERFACE ".Subscription"
|
|
|
06f198 |
|
|
|
06f198 |
static const gchar introspection_xml[] =
|
|
|
06f198 |
"<node>"
|
|
|
06f198 |
" <interface name='org.gnome.SettingsDaemon.Subscription'>"
|
|
|
06f198 |
" <method name='Register'>"
|
|
|
06f198 |
" <arg type='a{sv}' name='options' direction='in'/>"
|
|
|
06f198 |
" </method>"
|
|
|
06f198 |
" <method name='Unregister'/>"
|
|
|
06f198 |
+" <property name='InstalledProducts' type='aa{sv}' access='read'/>"
|
|
|
06f198 |
" <property name='SubscriptionStatus' type='u' access='read'/>"
|
|
|
06f198 |
" </interface>"
|
|
|
06f198 |
"</node>";
|
|
|
06f198 |
|
|
|
06f198 |
#define GSD_SUBSCRIPTION_MANAGER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GSD_TYPE_SUBSCRIPTION_MANAGER, GsdSubscriptionManagerPrivate))
|
|
|
06f198 |
|
|
|
06f198 |
typedef enum {
|
|
|
06f198 |
_RHSM_INTERFACE_CONFIG,
|
|
|
06f198 |
_RHSM_INTERFACE_REGISTER_SERVER,
|
|
|
06f198 |
_RHSM_INTERFACE_ATTACH,
|
|
|
06f198 |
_RHSM_INTERFACE_ENTITLEMENT,
|
|
|
06f198 |
_RHSM_INTERFACE_PRODUCTS,
|
|
|
06f198 |
_RHSM_INTERFACE_CONSUMER,
|
|
|
06f198 |
_RHSM_INTERFACE_SYSPURPOSE,
|
|
|
06f198 |
_RHSM_INTERFACE_LAST
|
|
|
06f198 |
} _RhsmInterface;
|
|
|
06f198 |
|
|
|
06f198 |
struct GsdSubscriptionManagerPrivate
|
|
|
06f198 |
{
|
|
|
06f198 |
/* D-Bus */
|
|
|
06f198 |
guint name_id;
|
|
|
06f198 |
GDBusNodeInfo *introspection_data;
|
|
|
06f198 |
GDBusConnection *connection;
|
|
|
06f198 |
GCancellable *bus_cancellable;
|
|
|
06f198 |
|
|
|
06f198 |
GDBusProxy *proxies[_RHSM_INTERFACE_LAST];
|
|
|
06f198 |
const gchar *userlang; /* owned by GLib internally */
|
|
|
06f198 |
GHashTable *config; /* str:str */
|
|
|
06f198 |
+ GPtrArray *installed_products;
|
|
|
06f198 |
gchar *address;
|
|
|
06f198 |
|
|
|
06f198 |
GTimer *timer_last_notified;
|
|
|
06f198 |
NotifyNotification *notification_expired;
|
|
|
06f198 |
NotifyNotification *notification_registered;
|
|
|
06f198 |
NotifyNotification *notification_registration_required;
|
|
|
06f198 |
GsdSubmanSubscriptionStatus subscription_status;
|
|
|
06f198 |
GsdSubmanSubscriptionStatus subscription_status_last;
|
|
|
06f198 |
};
|
|
|
06f198 |
|
|
|
06f198 |
enum {
|
|
|
06f198 |
PROP_0,
|
|
|
06f198 |
};
|
|
|
06f198 |
|
|
|
06f198 |
static void gsd_subscription_manager_class_init (GsdSubscriptionManagerClass *klass);
|
|
|
06f198 |
static void gsd_subscription_manager_init (GsdSubscriptionManager *subscription_manager);
|
|
|
06f198 |
static void gsd_subscription_manager_finalize (GObject *object);
|
|
|
06f198 |
|
|
|
06f198 |
G_DEFINE_TYPE (GsdSubscriptionManager, gsd_subscription_manager, G_TYPE_OBJECT)
|
|
|
06f198 |
|
|
|
06f198 |
+typedef struct
|
|
|
06f198 |
+{
|
|
|
06f198 |
+ gchar *product_name;
|
|
|
06f198 |
+ gchar *product_id;
|
|
|
06f198 |
+ gchar *version;
|
|
|
06f198 |
+ gchar *arch;
|
|
|
06f198 |
+ gchar *status;
|
|
|
06f198 |
+ gchar *starts;
|
|
|
06f198 |
+ gchar *ends;
|
|
|
06f198 |
+} ProductData;
|
|
|
06f198 |
+
|
|
|
06f198 |
+static void
|
|
|
06f198 |
+product_data_free (ProductData *product)
|
|
|
06f198 |
+{
|
|
|
06f198 |
+ g_free (product->product_name);
|
|
|
06f198 |
+ g_free (product->product_id);
|
|
|
06f198 |
+ g_free (product->version);
|
|
|
06f198 |
+ g_free (product->arch);
|
|
|
06f198 |
+ g_free (product->status);
|
|
|
06f198 |
+ g_free (product->starts);
|
|
|
06f198 |
+ g_free (product->ends);
|
|
|
06f198 |
+ g_free (product);
|
|
|
06f198 |
+}
|
|
|
06f198 |
+
|
|
|
06f198 |
+G_DEFINE_AUTOPTR_CLEANUP_FUNC (ProductData, product_data_free);
|
|
|
06f198 |
+
|
|
|
06f198 |
static gpointer manager_object = NULL;
|
|
|
06f198 |
|
|
|
06f198 |
GQuark
|
|
|
06f198 |
gsd_subscription_manager_error_quark (void)
|
|
|
06f198 |
{
|
|
|
06f198 |
static GQuark quark = 0;
|
|
|
06f198 |
if (!quark)
|
|
|
06f198 |
quark = g_quark_from_static_string ("gsd_subscription_manager_error");
|
|
|
06f198 |
return quark;
|
|
|
06f198 |
}
|
|
|
06f198 |
|
|
|
06f198 |
static GsdSubmanSubscriptionStatus
|
|
|
06f198 |
_client_subscription_status_from_text (const gchar *status_txt)
|
|
|
06f198 |
{
|
|
|
06f198 |
if (g_strcmp0 (status_txt, "Unknown") == 0)
|
|
|
06f198 |
return GSD_SUBMAN_SUBSCRIPTION_STATUS_UNKNOWN;
|
|
|
06f198 |
if (g_strcmp0 (status_txt, "Current") == 0)
|
|
|
06f198 |
return GSD_SUBMAN_SUBSCRIPTION_STATUS_VALID;
|
|
|
06f198 |
if (g_strcmp0 (status_txt, "Invalid") == 0)
|
|
|
06f198 |
return GSD_SUBMAN_SUBSCRIPTION_STATUS_INVALID;
|
|
|
06f198 |
if (g_strcmp0 (status_txt, "Disabled") == 0)
|
|
|
06f198 |
return GSD_SUBMAN_SUBSCRIPTION_STATUS_DISABLED;
|
|
|
06f198 |
if (g_strcmp0 (status_txt, "Insufficient") == 0)
|
|
|
06f198 |
return GSD_SUBMAN_SUBSCRIPTION_STATUS_PARTIALLY_VALID;
|
|
|
06f198 |
g_warning ("Unknown subscription status: %s", status_txt); // 'Current'?
|
|
|
06f198 |
return GSD_SUBMAN_SUBSCRIPTION_STATUS_UNKNOWN;
|
|
|
06f198 |
}
|
|
|
06f198 |
|
|
|
06f198 |
+static GVariant *
|
|
|
06f198 |
+_make_installed_products_variant (GPtrArray *installed_products)
|
|
|
06f198 |
+{
|
|
|
06f198 |
+ GVariantBuilder builder;
|
|
|
06f198 |
+ g_variant_builder_init (&builder, G_VARIANT_TYPE ("aa{sv}"));
|
|
|
06f198 |
+
|
|
|
06f198 |
+ for (guint i = 0; i < installed_products->len; i++) {
|
|
|
06f198 |
+ ProductData *product = g_ptr_array_index (installed_products, i);
|
|
|
06f198 |
+ g_auto(GVariantDict) dict;
|
|
|
06f198 |
+
|
|
|
06f198 |
+ g_variant_dict_init (&dict, NULL);
|
|
|
06f198 |
+
|
|
|
06f198 |
+ g_variant_dict_insert (&dict, "product-name", "s", product->product_name);
|
|
|
06f198 |
+ g_variant_dict_insert (&dict, "product-id", "s", product->product_id);
|
|
|
06f198 |
+ g_variant_dict_insert (&dict, "version", "s", product->version);
|
|
|
06f198 |
+ g_variant_dict_insert (&dict, "arch", "s", product->arch);
|
|
|
06f198 |
+ g_variant_dict_insert (&dict, "status", "s", product->status);
|
|
|
06f198 |
+ g_variant_dict_insert (&dict, "starts", "s", product->starts);
|
|
|
06f198 |
+ g_variant_dict_insert (&dict, "ends", "s", product->ends);
|
|
|
06f198 |
+
|
|
|
06f198 |
+ g_variant_builder_add_value (&builder, g_variant_dict_end (&dict));
|
|
|
06f198 |
+ }
|
|
|
06f198 |
+
|
|
|
06f198 |
+ return g_variant_builder_end (&builder);
|
|
|
06f198 |
+}
|
|
|
06f198 |
+
|
|
|
06f198 |
static void
|
|
|
06f198 |
_emit_property_changed (GsdSubscriptionManager *manager,
|
|
|
06f198 |
const gchar *property_name,
|
|
|
06f198 |
GVariant *property_value)
|
|
|
06f198 |
{
|
|
|
06f198 |
GsdSubscriptionManagerPrivate *priv = manager->priv;
|
|
|
06f198 |
GVariantBuilder builder;
|
|
|
06f198 |
GVariantBuilder invalidated_builder;
|
|
|
06f198 |
|
|
|
06f198 |
/* not yet connected */
|
|
|
06f198 |
if (priv->connection == NULL)
|
|
|
06f198 |
return;
|
|
|
06f198 |
|
|
|
06f198 |
/* build the dict */
|
|
|
06f198 |
g_variant_builder_init (&invalidated_builder, G_VARIANT_TYPE ("as"));
|
|
|
06f198 |
g_variant_builder_init (&builder, G_VARIANT_TYPE_ARRAY);
|
|
|
06f198 |
g_variant_builder_add (&builder,
|
|
|
06f198 |
"{sv}",
|
|
|
06f198 |
property_name,
|
|
|
06f198 |
property_value);
|
|
|
06f198 |
g_dbus_connection_emit_signal (priv->connection,
|
|
|
06f198 |
NULL,
|
|
|
06f198 |
GSD_SUBSCRIPTION_DBUS_PATH,
|
|
|
06f198 |
"org.freedesktop.DBus.Properties",
|
|
|
06f198 |
"PropertiesChanged",
|
|
|
06f198 |
g_variant_new ("(sa{sv}as)",
|
|
|
06f198 |
GSD_SUBSCRIPTION_DBUS_INTERFACE,
|
|
|
06f198 |
&builder,
|
|
|
06f198 |
&invalidated_builder),
|
|
|
06f198 |
NULL);
|
|
|
06f198 |
g_variant_builder_clear (&builder);
|
|
|
06f198 |
g_variant_builder_clear (&invalidated_builder);
|
|
|
06f198 |
}
|
|
|
06f198 |
|
|
|
06f198 |
+static gboolean
|
|
|
06f198 |
+_client_installed_products_update (GsdSubscriptionManager *manager, GError **error)
|
|
|
06f198 |
+{
|
|
|
06f198 |
+ GsdSubscriptionManagerPrivate *priv = manager->priv;
|
|
|
06f198 |
+ JsonNode *json_root;
|
|
|
06f198 |
+ JsonArray *json_products_array;
|
|
|
06f198 |
+ const gchar *json_txt = NULL;
|
|
|
06f198 |
+ g_autoptr(GVariant) val = NULL;
|
|
|
06f198 |
+ g_autoptr(JsonParser) json_parser = json_parser_new ();
|
|
|
06f198 |
+
|
|
|
06f198 |
+ val = g_dbus_proxy_call_sync (priv->proxies[_RHSM_INTERFACE_PRODUCTS],
|
|
|
06f198 |
+ "ListInstalledProducts",
|
|
|
06f198 |
+ g_variant_new ("(sa{sv}s)",
|
|
|
06f198 |
+ "" /* filter_string */,
|
|
|
06f198 |
+ NULL /* proxy_options */,
|
|
|
06f198 |
+ priv->userlang),
|
|
|
06f198 |
+ G_DBUS_CALL_FLAGS_NONE,
|
|
|
06f198 |
+ -1, NULL, error);
|
|
|
06f198 |
+ if (val == NULL)
|
|
|
06f198 |
+ return FALSE;
|
|
|
06f198 |
+ g_variant_get (val, "(&s)", &json_txt);
|
|
|
06f198 |
+ g_debug ("Products.ListInstalledProducts JSON: %s", json_txt);
|
|
|
06f198 |
+ if (!json_parser_load_from_data (json_parser, json_txt, -1, error))
|
|
|
06f198 |
+ return FALSE;
|
|
|
06f198 |
+ json_root = json_parser_get_root (json_parser);
|
|
|
06f198 |
+ json_products_array = json_node_get_array (json_root);
|
|
|
06f198 |
+ if (json_products_array == NULL) {
|
|
|
06f198 |
+ g_set_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_DATA,
|
|
|
06f198 |
+ "no InstalledProducts array in %s", json_txt);
|
|
|
06f198 |
+ return FALSE;
|
|
|
06f198 |
+ }
|
|
|
06f198 |
+
|
|
|
06f198 |
+ g_ptr_array_set_size (priv->installed_products, 0);
|
|
|
06f198 |
+
|
|
|
06f198 |
+ for (guint i = 0; i < json_array_get_length (json_products_array); i++) {
|
|
|
06f198 |
+ JsonArray *json_product = json_array_get_array_element (json_products_array, i);
|
|
|
06f198 |
+ g_autoptr(ProductData) product = g_new0 (ProductData, 1);
|
|
|
06f198 |
+
|
|
|
06f198 |
+ if (json_product == NULL)
|
|
|
06f198 |
+ continue;
|
|
|
06f198 |
+ if (json_array_get_length (json_product) < 8) {
|
|
|
06f198 |
+ g_debug ("Unexpected number of array elements in InstalledProducts JSON");
|
|
|
06f198 |
+ continue;
|
|
|
06f198 |
+ }
|
|
|
06f198 |
+
|
|
|
06f198 |
+ product->product_name = g_strdup (json_array_get_string_element (json_product, 0));
|
|
|
06f198 |
+ product->product_id = g_strdup (json_array_get_string_element (json_product, 1));
|
|
|
06f198 |
+ product->version = g_strdup (json_array_get_string_element (json_product, 2));
|
|
|
06f198 |
+ product->arch = g_strdup (json_array_get_string_element (json_product, 3));
|
|
|
06f198 |
+ product->status = g_strdup (json_array_get_string_element (json_product, 4));
|
|
|
06f198 |
+ product->starts = g_strdup (json_array_get_string_element (json_product, 6));
|
|
|
06f198 |
+ product->ends = g_strdup (json_array_get_string_element (json_product, 7));
|
|
|
06f198 |
+
|
|
|
06f198 |
+ g_ptr_array_add (priv->installed_products, g_steal_pointer (&product));
|
|
|
06f198 |
+ }
|
|
|
06f198 |
+
|
|
|
06f198 |
+ /* emit notification for g-c-c */
|
|
|
06f198 |
+ _emit_property_changed (manager, "InstalledProducts",
|
|
|
06f198 |
+ _make_installed_products_variant (priv->installed_products));
|
|
|
06f198 |
+
|
|
|
06f198 |
+ return TRUE;
|
|
|
06f198 |
+}
|
|
|
06f198 |
+
|
|
|
06f198 |
static gboolean
|
|
|
06f198 |
_client_subscription_status_update (GsdSubscriptionManager *manager, GError **error)
|
|
|
06f198 |
{
|
|
|
06f198 |
GsdSubscriptionManagerPrivate *priv = manager->priv;
|
|
|
06f198 |
JsonNode *json_root;
|
|
|
06f198 |
JsonObject *json_obj;
|
|
|
06f198 |
const gchar *json_txt = NULL;
|
|
|
06f198 |
const gchar *status_txt = NULL;
|
|
|
06f198 |
g_autoptr(GVariant) val = NULL;
|
|
|
06f198 |
g_autoptr(JsonParser) json_parser = json_parser_new ();
|
|
|
06f198 |
|
|
|
06f198 |
/* save old value */
|
|
|
06f198 |
priv->subscription_status_last = priv->subscription_status;
|
|
|
06f198 |
|
|
|
06f198 |
val = g_dbus_proxy_call_sync (priv->proxies[_RHSM_INTERFACE_ENTITLEMENT],
|
|
|
06f198 |
"GetStatus",
|
|
|
06f198 |
g_variant_new ("(ss)",
|
|
|
06f198 |
"", /* assumed as 'now' */
|
|
|
06f198 |
priv->userlang),
|
|
|
06f198 |
G_DBUS_CALL_FLAGS_NONE,
|
|
|
06f198 |
-1, NULL, error);
|
|
|
06f198 |
if (val == NULL)
|
|
|
06f198 |
return FALSE;
|
|
|
06f198 |
g_variant_get (val, "(&s)", &json_txt);
|
|
|
06f198 |
g_debug ("Entitlement.GetStatus JSON: %s", json_txt);
|
|
|
06f198 |
if (!json_parser_load_from_data (json_parser, json_txt, -1, error))
|
|
|
06f198 |
return FALSE;
|
|
|
06f198 |
json_root = json_parser_get_root (json_parser);
|
|
|
06f198 |
json_obj = json_node_get_object (json_root);
|
|
|
06f198 |
if (!json_object_has_member (json_obj, "status")) {
|
|
|
06f198 |
@@ -423,185 +541,195 @@ _client_register_with_keys (GsdSubscriptionManager *manager,
|
|
|
06f198 |
GError **error)
|
|
|
06f198 |
{
|
|
|
06f198 |
GsdSubscriptionManagerPrivate *priv = manager->priv;
|
|
|
06f198 |
g_autoptr(GSubprocess) subprocess = NULL;
|
|
|
06f198 |
|
|
|
06f198 |
/* apparently: "we can't send registration credentials over the regular
|
|
|
06f198 |
* system or session bus since those aren't really locked down..." */
|
|
|
06f198 |
if (!_client_register_start (manager, error))
|
|
|
06f198 |
return FALSE;
|
|
|
06f198 |
g_debug ("spawning %s", LIBEXECDIR "/gsd-subman-helper");
|
|
|
06f198 |
subprocess = g_subprocess_new (G_SUBPROCESS_FLAGS_STDERR_PIPE, error,
|
|
|
06f198 |
"pkexec", LIBEXECDIR "/gsd-subman-helper",
|
|
|
06f198 |
"--kind", "register-with-key",
|
|
|
06f198 |
"--address", priv->address,
|
|
|
06f198 |
"--hostname", hostname,
|
|
|
06f198 |
"--organisation", organisation,
|
|
|
06f198 |
"--activation-key", activation_key,
|
|
|
06f198 |
NULL);
|
|
|
06f198 |
if (subprocess == NULL) {
|
|
|
06f198 |
g_prefix_error (error, "failed to find pkexec: ");
|
|
|
06f198 |
return FALSE;
|
|
|
06f198 |
}
|
|
|
06f198 |
if (!_client_subprocess_wait_check (subprocess, error))
|
|
|
06f198 |
return FALSE;
|
|
|
06f198 |
|
|
|
06f198 |
/* FIXME: also do on error? */
|
|
|
06f198 |
if (!_client_register_stop (manager, error))
|
|
|
06f198 |
return FALSE;
|
|
|
06f198 |
if (!_client_subscription_status_update (manager, error))
|
|
|
06f198 |
return FALSE;
|
|
|
06f198 |
+ if (!_client_installed_products_update (manager, error))
|
|
|
06f198 |
+ return FALSE;
|
|
|
06f198 |
_client_maybe__show_notification (manager);
|
|
|
06f198 |
|
|
|
06f198 |
/* success */
|
|
|
06f198 |
return TRUE;
|
|
|
06f198 |
}
|
|
|
06f198 |
|
|
|
06f198 |
static gboolean
|
|
|
06f198 |
_client_register (GsdSubscriptionManager *manager,
|
|
|
06f198 |
const gchar *hostname,
|
|
|
06f198 |
const gchar *organisation,
|
|
|
06f198 |
const gchar *username,
|
|
|
06f198 |
const gchar *password,
|
|
|
06f198 |
GError **error)
|
|
|
06f198 |
{
|
|
|
06f198 |
GsdSubscriptionManagerPrivate *priv = manager->priv;
|
|
|
06f198 |
g_autoptr(GSubprocess) subprocess = NULL;
|
|
|
06f198 |
|
|
|
06f198 |
/* fallback */
|
|
|
06f198 |
if (organisation == NULL)
|
|
|
06f198 |
organisation = "";
|
|
|
06f198 |
|
|
|
06f198 |
/* apparently: "we can't send registration credentials over the regular
|
|
|
06f198 |
* system or session bus since those aren't really locked down..." */
|
|
|
06f198 |
if (!_client_register_start (manager, error))
|
|
|
06f198 |
return FALSE;
|
|
|
06f198 |
g_debug ("spawning %s", LIBEXECDIR "/gsd-subman-helper");
|
|
|
06f198 |
subprocess = g_subprocess_new (G_SUBPROCESS_FLAGS_STDERR_PIPE, error,
|
|
|
06f198 |
"pkexec", LIBEXECDIR "/gsd-subman-helper",
|
|
|
06f198 |
"--kind", "register-with-username",
|
|
|
06f198 |
"--address", priv->address,
|
|
|
06f198 |
"--hostname", hostname,
|
|
|
06f198 |
"--organisation", organisation,
|
|
|
06f198 |
"--username", username,
|
|
|
06f198 |
"--password", password,
|
|
|
06f198 |
NULL);
|
|
|
06f198 |
if (subprocess == NULL) {
|
|
|
06f198 |
g_prefix_error (error, "failed to find pkexec: ");
|
|
|
06f198 |
return FALSE;
|
|
|
06f198 |
}
|
|
|
06f198 |
if (!_client_subprocess_wait_check (subprocess, error))
|
|
|
06f198 |
return FALSE;
|
|
|
06f198 |
|
|
|
06f198 |
/* FIXME: also do on error? */
|
|
|
06f198 |
if (!_client_register_stop (manager, error))
|
|
|
06f198 |
return FALSE;
|
|
|
06f198 |
if (!_client_subscription_status_update (manager, error))
|
|
|
06f198 |
return FALSE;
|
|
|
06f198 |
+ if (!_client_installed_products_update (manager, error))
|
|
|
06f198 |
+ return FALSE;
|
|
|
06f198 |
_client_maybe__show_notification (manager);
|
|
|
06f198 |
return TRUE;
|
|
|
06f198 |
}
|
|
|
06f198 |
|
|
|
06f198 |
static gboolean
|
|
|
06f198 |
_client_unregister (GsdSubscriptionManager *manager, GError **error)
|
|
|
06f198 |
{
|
|
|
06f198 |
g_autoptr(GSubprocess) subprocess = NULL;
|
|
|
06f198 |
|
|
|
06f198 |
/* apparently: "we can't send registration credentials over the regular
|
|
|
06f198 |
* system or session bus since those aren't really locked down..." */
|
|
|
06f198 |
if (!_client_register_start (manager, error))
|
|
|
06f198 |
return FALSE;
|
|
|
06f198 |
g_debug ("spawning %s", LIBEXECDIR "/gsd-subman-helper");
|
|
|
06f198 |
subprocess = g_subprocess_new (G_SUBPROCESS_FLAGS_STDERR_PIPE, error,
|
|
|
06f198 |
"pkexec", LIBEXECDIR "/gsd-subman-helper",
|
|
|
06f198 |
"--kind", "unregister",
|
|
|
06f198 |
NULL);
|
|
|
06f198 |
if (subprocess == NULL) {
|
|
|
06f198 |
g_prefix_error (error, "failed to find pkexec: ");
|
|
|
06f198 |
return FALSE;
|
|
|
06f198 |
}
|
|
|
06f198 |
if (!_client_subprocess_wait_check (subprocess, error))
|
|
|
06f198 |
return FALSE;
|
|
|
06f198 |
if (!_client_subscription_status_update (manager, error))
|
|
|
06f198 |
return FALSE;
|
|
|
06f198 |
+ if (!_client_installed_products_update (manager, error))
|
|
|
06f198 |
+ return FALSE;
|
|
|
06f198 |
_client_maybe__show_notification (manager);
|
|
|
06f198 |
return TRUE;
|
|
|
06f198 |
}
|
|
|
06f198 |
|
|
|
06f198 |
static gboolean
|
|
|
06f198 |
_client_update_config (GsdSubscriptionManager *manager, GError **error)
|
|
|
06f198 |
{
|
|
|
06f198 |
GsdSubscriptionManagerPrivate *priv = manager->priv;
|
|
|
06f198 |
g_autoptr(GVariant) val = NULL;
|
|
|
06f198 |
g_autoptr(GVariant) val_server = NULL;
|
|
|
06f198 |
g_autoptr(GVariantDict) dict = NULL;
|
|
|
06f198 |
GVariantIter iter;
|
|
|
06f198 |
gchar *key;
|
|
|
06f198 |
gchar *value;
|
|
|
06f198 |
|
|
|
06f198 |
val = g_dbus_proxy_call_sync (priv->proxies[_RHSM_INTERFACE_CONFIG],
|
|
|
06f198 |
"GetAll",
|
|
|
06f198 |
g_variant_new ("(s)", priv->userlang),
|
|
|
06f198 |
G_DBUS_CALL_FLAGS_NONE,
|
|
|
06f198 |
-1, NULL, error);
|
|
|
06f198 |
if (val == NULL)
|
|
|
06f198 |
return FALSE;
|
|
|
06f198 |
dict = g_variant_dict_new (g_variant_get_child_value (val, 0));
|
|
|
06f198 |
val_server = g_variant_dict_lookup_value (dict, "server", G_VARIANT_TYPE("a{ss}"));
|
|
|
06f198 |
if (val_server != NULL) {
|
|
|
06f198 |
g_variant_iter_init (&iter, val_server);
|
|
|
06f198 |
while (g_variant_iter_next (&iter, "{ss}", &key, &value)) {
|
|
|
06f198 |
g_debug ("%s=%s", key, value);
|
|
|
06f198 |
g_hash_table_insert (priv->config,
|
|
|
06f198 |
g_steal_pointer (&key),
|
|
|
06f198 |
g_steal_pointer (&value));
|
|
|
06f198 |
}
|
|
|
06f198 |
}
|
|
|
06f198 |
return TRUE;
|
|
|
06f198 |
}
|
|
|
06f198 |
|
|
|
06f198 |
static void
|
|
|
06f198 |
_subman_proxy_signal_cb (GDBusProxy *proxy,
|
|
|
06f198 |
const gchar *sender_name,
|
|
|
06f198 |
const gchar *signal_name,
|
|
|
06f198 |
GVariant *parameters,
|
|
|
06f198 |
GsdSubscriptionManager *manager)
|
|
|
06f198 |
{
|
|
|
06f198 |
g_autoptr(GError) error = NULL;
|
|
|
06f198 |
if (!_client_syspurpose_update (manager, &error)) {
|
|
|
06f198 |
g_warning ("failed to update syspurpose: %s", error->message);
|
|
|
06f198 |
g_clear_error (&error);
|
|
|
06f198 |
}
|
|
|
06f198 |
if (!_client_subscription_status_update (manager, &error)) {
|
|
|
06f198 |
g_warning ("failed to update subscription status: %s", error->message);
|
|
|
06f198 |
g_clear_error (&error);
|
|
|
06f198 |
}
|
|
|
06f198 |
+ if (!_client_installed_products_update (manager, &error)) {
|
|
|
06f198 |
+ g_warning ("failed to update installed products: %s", error->message);
|
|
|
06f198 |
+ g_clear_error (&error);
|
|
|
06f198 |
+ }
|
|
|
06f198 |
_client_maybe__show_notification (manager);
|
|
|
06f198 |
}
|
|
|
06f198 |
|
|
|
06f198 |
static void
|
|
|
06f198 |
_client_unload (GsdSubscriptionManager *manager)
|
|
|
06f198 |
{
|
|
|
06f198 |
GsdSubscriptionManagerPrivate *priv = manager->priv;
|
|
|
06f198 |
for (guint i = 0; i < _RHSM_INTERFACE_LAST; i++)
|
|
|
06f198 |
g_clear_object (&priv->proxies[i]);
|
|
|
06f198 |
g_hash_table_unref (priv->config);
|
|
|
06f198 |
}
|
|
|
06f198 |
|
|
|
06f198 |
static const gchar *
|
|
|
06f198 |
_rhsm_interface_to_string (_RhsmInterface kind)
|
|
|
06f198 |
{
|
|
|
06f198 |
if (kind == _RHSM_INTERFACE_CONFIG)
|
|
|
06f198 |
return "Config";
|
|
|
06f198 |
if (kind == _RHSM_INTERFACE_REGISTER_SERVER)
|
|
|
06f198 |
return "RegisterServer";
|
|
|
06f198 |
if (kind == _RHSM_INTERFACE_ATTACH)
|
|
|
06f198 |
return "Attach";
|
|
|
06f198 |
if (kind == _RHSM_INTERFACE_ENTITLEMENT)
|
|
|
06f198 |
return "Entitlement";
|
|
|
06f198 |
if (kind == _RHSM_INTERFACE_PRODUCTS)
|
|
|
06f198 |
return "Products";
|
|
|
06f198 |
if (kind == _RHSM_INTERFACE_CONSUMER)
|
|
|
06f198 |
return "Consumer";
|
|
|
06f198 |
if (kind == _RHSM_INTERFACE_SYSPURPOSE)
|
|
|
06f198 |
return "Syspurpose";
|
|
|
06f198 |
return NULL;
|
|
|
06f198 |
@@ -613,60 +741,62 @@ _client_load (GsdSubscriptionManager *manager, GError **error)
|
|
|
06f198 |
GsdSubscriptionManagerPrivate *priv = manager->priv;
|
|
|
06f198 |
|
|
|
06f198 |
priv->config = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
|
|
|
06f198 |
|
|
|
06f198 |
/* connect to all the interfaces on the *different* objects :| */
|
|
|
06f198 |
for (guint i = 0; i < _RHSM_INTERFACE_LAST; i++) {
|
|
|
06f198 |
const gchar *kind = _rhsm_interface_to_string (i);
|
|
|
06f198 |
g_autofree gchar *opath = g_strdup_printf ("/com/redhat/RHSM1/%s", kind);
|
|
|
06f198 |
g_autofree gchar *iface = g_strdup_printf ("com.redhat.RHSM1.%s", kind);
|
|
|
06f198 |
priv->proxies[i] =
|
|
|
06f198 |
g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM,
|
|
|
06f198 |
G_DBUS_PROXY_FLAGS_NONE,
|
|
|
06f198 |
NULL,
|
|
|
06f198 |
"com.redhat.RHSM1",
|
|
|
06f198 |
opath, iface,
|
|
|
06f198 |
NULL,
|
|
|
06f198 |
error);
|
|
|
06f198 |
if (priv->proxies[i] == NULL)
|
|
|
06f198 |
return FALSE;
|
|
|
06f198 |
/* we want to get notified if the status of the system changes */
|
|
|
06f198 |
g_signal_connect (priv->proxies[i], "g-signal",
|
|
|
06f198 |
G_CALLBACK (_subman_proxy_signal_cb), manager);
|
|
|
06f198 |
}
|
|
|
06f198 |
|
|
|
06f198 |
/* get initial status */
|
|
|
06f198 |
priv->userlang = "";
|
|
|
06f198 |
if (!_client_update_config (manager, error))
|
|
|
06f198 |
return FALSE;
|
|
|
06f198 |
if (!_client_subscription_status_update (manager, error))
|
|
|
06f198 |
return FALSE;
|
|
|
06f198 |
+ if (!_client_installed_products_update (manager, error))
|
|
|
06f198 |
+ return FALSE;
|
|
|
06f198 |
if (!_client_syspurpose_update (manager, error))
|
|
|
06f198 |
return FALSE;
|
|
|
06f198 |
|
|
|
06f198 |
/* success */
|
|
|
06f198 |
return TRUE;
|
|
|
06f198 |
}
|
|
|
06f198 |
|
|
|
06f198 |
gboolean
|
|
|
06f198 |
gsd_subscription_manager_start (GsdSubscriptionManager *manager, GError **error)
|
|
|
06f198 |
{
|
|
|
06f198 |
gboolean ret;
|
|
|
06f198 |
g_debug ("Starting subscription manager");
|
|
|
06f198 |
gnome_settings_profile_start (NULL);
|
|
|
06f198 |
ret = _client_load (manager, error);
|
|
|
06f198 |
_client_maybe__show_notification (manager);
|
|
|
06f198 |
gnome_settings_profile_end (NULL);
|
|
|
06f198 |
return ret;
|
|
|
06f198 |
}
|
|
|
06f198 |
|
|
|
06f198 |
void
|
|
|
06f198 |
gsd_subscription_manager_stop (GsdSubscriptionManager *manager)
|
|
|
06f198 |
{
|
|
|
06f198 |
g_debug ("Stopping subscription manager");
|
|
|
06f198 |
_client_unload (manager);
|
|
|
06f198 |
}
|
|
|
06f198 |
|
|
|
06f198 |
static void
|
|
|
06f198 |
gsd_subscription_manager_class_init (GsdSubscriptionManagerClass *klass)
|
|
|
06f198 |
{
|
|
|
06f198 |
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
|
|
06f198 |
@@ -676,60 +806,61 @@ gsd_subscription_manager_class_init (GsdSubscriptionManagerClass *klass)
|
|
|
06f198 |
}
|
|
|
06f198 |
|
|
|
06f198 |
static void
|
|
|
06f198 |
_launch_info_overview (void)
|
|
|
06f198 |
{
|
|
|
06f198 |
const gchar *argv[] = { "gnome-control-center", "info-overview", NULL };
|
|
|
06f198 |
g_debug ("Running gnome-control-center info-overview");
|
|
|
06f198 |
g_spawn_async (NULL, (gchar **) argv, NULL, G_SPAWN_SEARCH_PATH,
|
|
|
06f198 |
NULL, NULL, NULL, NULL);
|
|
|
06f198 |
}
|
|
|
06f198 |
|
|
|
06f198 |
static void
|
|
|
06f198 |
_notify_closed_cb (NotifyNotification *notification, gpointer user_data)
|
|
|
06f198 |
{
|
|
|
06f198 |
/* FIXME: only launch when clicking on the main body, not the window close */
|
|
|
06f198 |
if (notify_notification_get_closed_reason (notification) == 0x400)
|
|
|
06f198 |
_launch_info_overview ();
|
|
|
06f198 |
}
|
|
|
06f198 |
|
|
|
06f198 |
static void
|
|
|
06f198 |
_notify_clicked_cb (NotifyNotification *notification, char *action, gpointer user_data)
|
|
|
06f198 |
{
|
|
|
06f198 |
_launch_info_overview ();
|
|
|
06f198 |
}
|
|
|
06f198 |
|
|
|
06f198 |
static void
|
|
|
06f198 |
gsd_subscription_manager_init (GsdSubscriptionManager *manager)
|
|
|
06f198 |
{
|
|
|
06f198 |
GsdSubscriptionManagerPrivate *priv = manager->priv = GSD_SUBSCRIPTION_MANAGER_GET_PRIVATE (manager);
|
|
|
06f198 |
|
|
|
06f198 |
+ priv->installed_products = g_ptr_array_new_with_free_func ((GDestroyNotify) product_data_free);
|
|
|
06f198 |
priv->timer_last_notified = g_timer_new ();
|
|
|
06f198 |
|
|
|
06f198 |
/* expired */
|
|
|
06f198 |
priv->notification_expired =
|
|
|
06f198 |
notify_notification_new (_("Subscription Has Expired"),
|
|
|
06f198 |
_("Add or renew a subscription to continue receiving software updates."),
|
|
|
06f198 |
NULL);
|
|
|
06f198 |
notify_notification_set_app_name (priv->notification_expired, _("Subscription"));
|
|
|
06f198 |
notify_notification_set_hint_string (priv->notification_expired, "desktop-entry", "subman-panel");
|
|
|
06f198 |
notify_notification_set_hint_string (priv->notification_expired, "x-gnome-privacy-scope", "system");
|
|
|
06f198 |
notify_notification_set_urgency (priv->notification_expired, NOTIFY_URGENCY_CRITICAL);
|
|
|
06f198 |
notify_notification_add_action (priv->notification_expired,
|
|
|
06f198 |
"info-overview", _("Subscribe System…"),
|
|
|
06f198 |
_notify_clicked_cb,
|
|
|
06f198 |
manager, NULL);
|
|
|
06f198 |
g_signal_connect (priv->notification_expired, "closed",
|
|
|
06f198 |
G_CALLBACK (_notify_closed_cb), manager);
|
|
|
06f198 |
|
|
|
06f198 |
/* registered */
|
|
|
06f198 |
priv->notification_registered =
|
|
|
06f198 |
notify_notification_new (_("Registration Successful"),
|
|
|
06f198 |
_("The system has been registered and software updates have been enabled."),
|
|
|
06f198 |
NULL);
|
|
|
06f198 |
notify_notification_set_app_name (priv->notification_registered, _("Subscription"));
|
|
|
06f198 |
notify_notification_set_hint_string (priv->notification_registered, "desktop-entry", "subman-panel");
|
|
|
06f198 |
notify_notification_set_hint_string (priv->notification_registered, "x-gnome-privacy-scope", "system");
|
|
|
06f198 |
notify_notification_set_urgency (priv->notification_registered, NOTIFY_URGENCY_CRITICAL);
|
|
|
06f198 |
g_signal_connect (priv->notification_registered, "closed",
|
|
|
06f198 |
G_CALLBACK (_notify_closed_cb), manager);
|
|
|
06f198 |
|
|
|
06f198 |
@@ -740,60 +871,61 @@ gsd_subscription_manager_init (GsdSubscriptionManager *manager)
|
|
|
06f198 |
NULL);
|
|
|
06f198 |
notify_notification_set_app_name (priv->notification_registration_required, _("Subscription"));
|
|
|
06f198 |
notify_notification_set_hint_string (priv->notification_registration_required, "desktop-entry", "subman-panel");
|
|
|
06f198 |
notify_notification_set_hint_string (priv->notification_registration_required, "x-gnome-privacy-scope", "system");
|
|
|
06f198 |
notify_notification_set_urgency (priv->notification_registration_required, NOTIFY_URGENCY_CRITICAL);
|
|
|
06f198 |
notify_notification_add_action (priv->notification_registration_required,
|
|
|
06f198 |
"info-overview", _("Register System…"),
|
|
|
06f198 |
_notify_clicked_cb,
|
|
|
06f198 |
manager, NULL);
|
|
|
06f198 |
g_signal_connect (priv->notification_registration_required, "closed",
|
|
|
06f198 |
G_CALLBACK (_notify_closed_cb), manager);
|
|
|
06f198 |
}
|
|
|
06f198 |
|
|
|
06f198 |
static void
|
|
|
06f198 |
gsd_subscription_manager_finalize (GObject *object)
|
|
|
06f198 |
{
|
|
|
06f198 |
GsdSubscriptionManager *manager;
|
|
|
06f198 |
|
|
|
06f198 |
g_return_if_fail (object != NULL);
|
|
|
06f198 |
g_return_if_fail (GSD_IS_SUBSCRIPTION_MANAGER (object));
|
|
|
06f198 |
|
|
|
06f198 |
manager = GSD_SUBSCRIPTION_MANAGER (object);
|
|
|
06f198 |
|
|
|
06f198 |
gsd_subscription_manager_stop (manager);
|
|
|
06f198 |
|
|
|
06f198 |
if (manager->priv->bus_cancellable != NULL) {
|
|
|
06f198 |
g_cancellable_cancel (manager->priv->bus_cancellable);
|
|
|
06f198 |
g_clear_object (&manager->priv->bus_cancellable);
|
|
|
06f198 |
}
|
|
|
06f198 |
|
|
|
06f198 |
+ g_clear_pointer (&manager->priv->installed_products, g_ptr_array_unref);
|
|
|
06f198 |
g_clear_pointer (&manager->priv->introspection_data, g_dbus_node_info_unref);
|
|
|
06f198 |
g_clear_object (&manager->priv->connection);
|
|
|
06f198 |
g_clear_object (&manager->priv->notification_expired);
|
|
|
06f198 |
g_clear_object (&manager->priv->notification_registered);
|
|
|
06f198 |
g_timer_destroy (manager->priv->timer_last_notified);
|
|
|
06f198 |
|
|
|
06f198 |
if (manager->priv->name_id != 0) {
|
|
|
06f198 |
g_bus_unown_name (manager->priv->name_id);
|
|
|
06f198 |
manager->priv->name_id = 0;
|
|
|
06f198 |
}
|
|
|
06f198 |
|
|
|
06f198 |
G_OBJECT_CLASS (gsd_subscription_manager_parent_class)->finalize (object);
|
|
|
06f198 |
}
|
|
|
06f198 |
|
|
|
06f198 |
static void
|
|
|
06f198 |
handle_method_call (GDBusConnection *connection,
|
|
|
06f198 |
const gchar *sender,
|
|
|
06f198 |
const gchar *object_path,
|
|
|
06f198 |
const gchar *interface_name,
|
|
|
06f198 |
const gchar *method_name,
|
|
|
06f198 |
GVariant *parameters,
|
|
|
06f198 |
GDBusMethodInvocation *invocation,
|
|
|
06f198 |
gpointer user_data)
|
|
|
06f198 |
{
|
|
|
06f198 |
GsdSubscriptionManager *manager = GSD_SUBSCRIPTION_MANAGER (user_data);
|
|
|
06f198 |
g_autoptr(GError) error = NULL;
|
|
|
06f198 |
|
|
|
06f198 |
if (g_strcmp0 (method_name, "Register") == 0) {
|
|
|
06f198 |
const gchar *organisation = NULL;
|
|
|
06f198 |
const gchar *hostname = NULL;
|
|
|
06f198 |
@@ -857,60 +989,63 @@ handle_method_call (GDBusConnection *connection,
|
|
|
06f198 |
if (!_client_unregister (manager, &error)) {
|
|
|
06f198 |
g_dbus_method_invocation_return_gerror (invocation, error);
|
|
|
06f198 |
return;
|
|
|
06f198 |
}
|
|
|
06f198 |
g_dbus_method_invocation_return_value (invocation, NULL);
|
|
|
06f198 |
} else {
|
|
|
06f198 |
g_assert_not_reached ();
|
|
|
06f198 |
}
|
|
|
06f198 |
}
|
|
|
06f198 |
|
|
|
06f198 |
static GVariant *
|
|
|
06f198 |
handle_get_property (GDBusConnection *connection,
|
|
|
06f198 |
const gchar *sender,
|
|
|
06f198 |
const gchar *object_path,
|
|
|
06f198 |
const gchar *interface_name,
|
|
|
06f198 |
const gchar *property_name,
|
|
|
06f198 |
GError **error, gpointer user_data)
|
|
|
06f198 |
{
|
|
|
06f198 |
GsdSubscriptionManager *manager = GSD_SUBSCRIPTION_MANAGER (user_data);
|
|
|
06f198 |
GsdSubscriptionManagerPrivate *priv = manager->priv;
|
|
|
06f198 |
|
|
|
06f198 |
if (g_strcmp0 (interface_name, GSD_SUBSCRIPTION_DBUS_INTERFACE) != 0) {
|
|
|
06f198 |
g_set_error (error, G_DBUS_ERROR, G_DBUS_ERROR_FAILED,
|
|
|
06f198 |
"No such interface: %s", interface_name);
|
|
|
06f198 |
return NULL;
|
|
|
06f198 |
}
|
|
|
06f198 |
|
|
|
06f198 |
if (g_strcmp0 (property_name, "SubscriptionStatus") == 0)
|
|
|
06f198 |
return g_variant_new_uint32 (priv->subscription_status);
|
|
|
06f198 |
|
|
|
06f198 |
+ if (g_strcmp0 (property_name, "InstalledProducts") == 0)
|
|
|
06f198 |
+ return _make_installed_products_variant (priv->installed_products);
|
|
|
06f198 |
+
|
|
|
06f198 |
g_set_error (error, G_DBUS_ERROR, G_DBUS_ERROR_FAILED,
|
|
|
06f198 |
"Failed to get property: %s", property_name);
|
|
|
06f198 |
return NULL;
|
|
|
06f198 |
}
|
|
|
06f198 |
|
|
|
06f198 |
static gboolean
|
|
|
06f198 |
handle_set_property (GDBusConnection *connection,
|
|
|
06f198 |
const gchar *sender,
|
|
|
06f198 |
const gchar *object_path,
|
|
|
06f198 |
const gchar *interface_name,
|
|
|
06f198 |
const gchar *property_name,
|
|
|
06f198 |
GVariant *value,
|
|
|
06f198 |
GError **error, gpointer user_data)
|
|
|
06f198 |
{
|
|
|
06f198 |
if (g_strcmp0 (interface_name, GSD_SUBSCRIPTION_DBUS_INTERFACE) != 0) {
|
|
|
06f198 |
g_set_error (error, G_DBUS_ERROR, G_DBUS_ERROR_FAILED,
|
|
|
06f198 |
"No such interface: %s", interface_name);
|
|
|
06f198 |
return FALSE;
|
|
|
06f198 |
}
|
|
|
06f198 |
g_set_error (error, G_DBUS_ERROR, G_DBUS_ERROR_FAILED,
|
|
|
06f198 |
"No such property: %s", property_name);
|
|
|
06f198 |
return FALSE;
|
|
|
06f198 |
}
|
|
|
06f198 |
|
|
|
06f198 |
static const GDBusInterfaceVTable interface_vtable =
|
|
|
06f198 |
{
|
|
|
06f198 |
handle_method_call,
|
|
|
06f198 |
handle_get_property,
|
|
|
06f198 |
handle_set_property
|
|
|
06f198 |
};
|
|
|
06f198 |
--
|
|
|
06f198 |
2.30.0
|
|
|
06f198 |
|