diff options
Diffstat (limited to 'src/apt-watcher.c')
-rw-r--r-- | src/apt-watcher.c | 506 |
1 files changed, 146 insertions, 360 deletions
diff --git a/src/apt-watcher.c b/src/apt-watcher.c index 481029a..6e8a5c9 100644 --- a/src/apt-watcher.c +++ b/src/apt-watcher.c @@ -17,150 +17,113 @@ You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include <gio/gio.h> +// Conor - 6/2/2012 +// Please pull in packagekit's client lib +// using apt-get install --no-install-recommends libpackagekit-glib2-dev +// make sure you don't install package-kit +#define I_KNOW_THE_PACKAGEKIT_GLIB2_API_IS_SUBJECT_TO_CHANGE + #include <glib/gi18n.h> +#include <packagekit-glib2/packagekit.h> #include "apt-watcher.h" -#include "apt-transaction.h" +#include "dbus-shared-names.h" static guint watcher_id; struct _AptWatcher { GObject parent_instance; - guint reboot_query; - GCancellable * proxy_cancel; - GDBusProxy * proxy; SessionDbus* session_dbus_interface; DbusmenuMenuitem* apt_item; AptState current_state; - AptTransaction* current_transaction; + GCancellable * proxy_cancel; + GDBusProxy * proxy; }; - -static void -apt_watcher_on_name_appeared (GDBusConnection *connection, - const gchar *name, - const gchar *name_owner, - gpointer user_data); -static void -apt_watcher_on_name_vanished (GDBusConnection *connection, - const gchar *name, - gpointer user_data); -static void fetch_proxy_cb (GObject * object, - GAsyncResult * res, - gpointer user_data); - -static void apt_watcher_upgrade_system_cb (GObject * obj, - GAsyncResult * res, - gpointer user_data); - - -static void apt_watcher_show_apt_dialog (DbusmenuMenuitem* mi, - guint timestamp, - gpointer userdata); - -static void apt_watcher_signal_cb (GDBusProxy* proxy, - gchar* sender_name, - gchar* signal_name, - GVariant* parameters, - gpointer user_data); -static void apt_watcher_manage_transactions (AptWatcher* self, - gchar* transaction_id); -static gboolean apt_watcher_query_reboot_status (gpointer self); -static void apt_watcher_transaction_state_simulation_update_cb (AptTransaction* trans, - gint update, - gpointer user_data); -static void apt_watcher_transaction_state_real_update_cb (AptTransaction* trans, - gint update, - gpointer user_data); -static gboolean apt_watcher_start_apt_interaction (gpointer data); - + G_DEFINE_TYPE (AptWatcher, apt_watcher, G_TYPE_OBJECT); + static void -apt_watcher_init (AptWatcher *self) +get_updates_complete (GObject *source_object, + GAsyncResult *res, + gpointer user_data) { - self->current_state = UP_TO_DATE; - self->proxy_cancel = g_cancellable_new(); - self->proxy = NULL; - self->reboot_query = 0; - self->current_transaction = NULL; - g_timeout_add_seconds (60, - apt_watcher_start_apt_interaction, - self); -} + g_return_if_fail (APT_IS_WATCHER (user_data)); + AptWatcher* self = APT_WATCHER (user_data); -static gboolean -apt_watcher_start_apt_interaction (gpointer data) -{ - g_return_val_if_fail (APT_IS_WATCHER (data), FALSE); - AptWatcher* self = APT_WATCHER (data); - g_dbus_proxy_new_for_bus (G_BUS_TYPE_SYSTEM, - G_DBUS_PROXY_FLAGS_NONE, - NULL, - "org.debian.apt", - "/org/debian/apt", - "org.debian.apt", - self->proxy_cancel, - fetch_proxy_cb, - self); - return FALSE; -} + PkResults *results; + GError *error = NULL; + results = pk_client_generic_finish (PK_CLIENT(source_object), res, &error); + + if (error != NULL){ + g_warning ("Unable to query for updates - error - %s", error->message); + return; + } -static void -apt_watcher_finalize (GObject *object) -{ - g_bus_unwatch_name (watcher_id); - AptWatcher* self = APT_WATCHER (object); - - if (self->proxy != NULL) - g_object_unref (self->proxy); + GPtrArray *packages; + packages = pk_results_get_package_array (results); - G_OBJECT_CLASS (apt_watcher_parent_class)->finalize (object); + const gchar* disposition; + disposition = dbusmenu_menuitem_property_get (self->apt_item, + DBUSMENU_MENUITEM_PROP_DISPOSITION); + gboolean do_update; + do_update = g_strcmp0 (disposition, DBUSMENU_MENUITEM_DISPOSITION_ALERT) != 0; + + if (packages->len > 0){ + g_print ("Apparently we have updates available - change dbmitem %i", do_update); + if (do_update) + dbusmenu_menuitem_property_set (self->apt_item, + DBUSMENU_MENUITEM_PROP_LABEL, + _("Updates Available…")); + } + else{ + g_print ("No updates available - change dbmitem - %i", do_update); + if (do_update) + dbusmenu_menuitem_property_set (self->apt_item, + DBUSMENU_MENUITEM_PROP_LABEL, + _("Software Up to Date")); + } + g_ptr_array_unref (packages); + g_object_unref (results); + g_object_unref (source_object); } static void -apt_watcher_class_init (AptWatcherClass *klass) +apt_watcher_check_for_updates (AptWatcher* self) { - GObjectClass* object_class = G_OBJECT_CLASS (klass); - object_class->finalize = apt_watcher_finalize; + PkClient* client; + client = pk_client_new (); + + pk_client_get_updates_async (client, + PK_FILTER_ENUM_NONE, + NULL, NULL, NULL, + (GAsyncReadyCallback)get_updates_complete, + self); } -static void -fetch_proxy_cb (GObject * object, GAsyncResult * res, gpointer user_data) +static void apt_watcher_signal_cb ( GDBusProxy* proxy, + gchar* sender_name, + gchar* signal_name, + GVariant* parameters, + gpointer user_data) { - GError * error = NULL; - - AptWatcher* self = APT_WATCHER(user_data); - g_return_if_fail(self != NULL); - - GDBusProxy * proxy = g_dbus_proxy_new_for_bus_finish(res, &error); - - if (self->proxy_cancel != NULL) { - g_object_unref(self->proxy_cancel); - self->proxy_cancel = NULL; - } - - if (error != NULL) { - g_warning("Could not grab DBus proxy for %s: %s", - "org.debian.apt", error->message); - g_error_free(error); - return; - } + g_return_if_fail (APT_IS_WATCHER (user_data)); + AptWatcher* self = APT_WATCHER (user_data); - self->proxy = proxy; - // Set up the watch. - watcher_id = g_bus_watch_name (G_BUS_TYPE_SYSTEM, - "org.debian.apt", - G_BUS_NAME_WATCHER_FLAGS_NONE, - apt_watcher_on_name_appeared, - apt_watcher_on_name_vanished, - self, - NULL); - - g_signal_connect (self->proxy, - "g-signal", - G_CALLBACK(apt_watcher_signal_cb), - self); + g_debug ("apt-watcher-signal cb signal name - %s", signal_name); + if (g_strcmp0(signal_name, "UpdatesChanged") == 0){ + g_debug ("updates changed signal received"); + apt_watcher_check_for_updates (self); + } + else if (g_strcmp0(signal_name, "RestartScheduled") == 0) { + g_debug ("RestartScheduled signal received"); + dbusmenu_menuitem_property_set (self->apt_item, + DBUSMENU_MENUITEM_PROP_LABEL, + _("Restart to Complete Updates…")); + dbusmenu_menuitem_property_set (self->apt_item, + DBUSMENU_MENUITEM_PROP_DISPOSITION, + DBUSMENU_MENUITEM_DISPOSITION_ALERT); + } } static void @@ -170,21 +133,12 @@ apt_watcher_on_name_appeared (GDBusConnection *connection, gpointer user_data) { g_return_if_fail (APT_IS_WATCHER (user_data)); - AptWatcher* watcher = APT_WATCHER (user_data); + // AptWatcher* watcher = APT_WATCHER (user_data); g_print ("Name %s on %s is owned by %s\n", name, "the system bus", name_owner); - - g_dbus_proxy_call (watcher->proxy, - "UpgradeSystem", - g_variant_new("(b)", TRUE), - G_DBUS_CALL_FLAGS_NONE, - -1, - NULL, - apt_watcher_upgrade_system_cb, - user_data); } @@ -199,36 +153,61 @@ apt_watcher_on_name_vanished (GDBusConnection *connection, } static void -apt_watcher_upgrade_system_cb (GObject * obj, - GAsyncResult * res, - gpointer user_data) +fetch_proxy_cb (GObject * object, GAsyncResult * res, gpointer user_data) { - g_return_if_fail (APT_IS_WATCHER (user_data)); - AptWatcher* self = APT_WATCHER (user_data); + GError * error = NULL; - GError * error = NULL; - GVariant * result; + AptWatcher* self = APT_WATCHER(user_data); + g_return_if_fail(self != NULL); - result = g_dbus_proxy_call_finish(self->proxy, res, &error); + GDBusProxy * proxy = g_dbus_proxy_new_for_bus_finish (res, &error); - if (error != NULL) { - g_warning ("unable to complete the UpgradeSystem apt call"); - g_error_free (error); - return; - } - - gchar* transaction_id = NULL; - g_variant_get (result, "(s)", &transaction_id); + if (self->proxy_cancel != NULL) { + g_object_unref (self->proxy_cancel); + self->proxy_cancel = NULL; + } - if (transaction_id == NULL){ - g_warning ("apt_watcher_upgrade_system_cb - transaction id is null"); + if (error != NULL) { + g_warning("Could not grab DBus proxy for %s: %s", + "org.debian.apt", error->message); + g_error_free(error); return; - } - - apt_watcher_manage_transactions (self, transaction_id); - + } + + self->proxy = proxy; + // Set up the watch. + watcher_id = g_bus_watch_name (G_BUS_TYPE_SYSTEM, + "org.freedesktop.PackageKit", + G_BUS_NAME_WATCHER_FLAGS_NONE, + apt_watcher_on_name_appeared, + apt_watcher_on_name_vanished, + self, + NULL); + g_signal_connect (self->proxy, + "g-signal", + G_CALLBACK(apt_watcher_signal_cb), + self); +} + +static gboolean +apt_watcher_start_apt_interaction (gpointer data) +{ + g_return_val_if_fail (APT_IS_WATCHER (data), FALSE); + AptWatcher* self = APT_WATCHER (data); + g_dbus_proxy_new_for_bus (G_BUS_TYPE_SYSTEM, + G_DBUS_PROXY_FLAGS_NONE, + NULL, + "org.freedesktop.PackageKit", + "/org/freedesktop/PackageKit", + "org.freedesktop.PackageKit", + self->proxy_cancel, + fetch_proxy_cb, + self); + apt_watcher_check_for_updates (self); + return FALSE; } + static void apt_watcher_show_apt_dialog (DbusmenuMenuitem * mi, guint timestamp, @@ -261,224 +240,31 @@ apt_watcher_show_apt_dialog (DbusmenuMenuitem * mi, } static void -apt_watcher_transaction_state_real_update_cb (AptTransaction* trans, - gint update, - gpointer user_data) -{ - g_debug ("apt-watcher -transaction update %i", update); - g_return_if_fail (APT_IS_WATCHER (user_data)); - AptWatcher* self = APT_WATCHER (user_data); - - AptState state = (AptState)update; - if (self->current_state != RESTART_NEEDED) - { - if (state == UP_TO_DATE){ - dbusmenu_menuitem_property_set (self->apt_item, - DBUSMENU_MENUITEM_PROP_LABEL, - _("Software Up to Date")); - self->current_state = state; - } - else if (state == UPDATES_AVAILABLE){ - dbusmenu_menuitem_property_set (self->apt_item, - DBUSMENU_MENUITEM_PROP_LABEL, - _("Updates Available…")); - self->current_state = state; - } - else if (state == UPGRADE_IN_PROGRESS){ - dbusmenu_menuitem_property_set (self->apt_item, - DBUSMENU_MENUITEM_PROP_LABEL, - _("Updates Installing…")); - self->current_state = state; - } - else if (state == FINISHED){ - gboolean query_again = FALSE; - - // Only query if the previous state was an upgrade. - if (self->current_state != UPGRADE_IN_PROGRESS){ - query_again = TRUE; - } - else{ - if (self->reboot_query != 0){ - g_source_remove (self->reboot_query); - self->reboot_query = 0; - } - self->reboot_query = g_timeout_add_seconds (1, - apt_watcher_query_reboot_status, - self); - } - self->current_state = state; - - g_object_unref (G_OBJECT(self->current_transaction)); - self->current_transaction = NULL; - - // It is impossible to determine from a 'real' transaction whether - // updates are available therefore it is necessary to check again via a - // simulation whether there are updates available. - if (query_again){ - g_dbus_proxy_call (self->proxy, - "UpgradeSystem", - g_variant_new("(b)", TRUE), - G_DBUS_CALL_FLAGS_NONE, - -1, - NULL, - apt_watcher_upgrade_system_cb, - self); - } - } - } -} - - -static void -apt_watcher_transaction_state_simulation_update_cb (AptTransaction* trans, - gint update, - gpointer user_data) -{ - g_debug ("apt-watcher -transaction update %i", update); - g_return_if_fail (APT_IS_WATCHER (user_data)); - AptWatcher* self = APT_WATCHER (user_data); - - AptState state = (AptState)update; - if (self->current_state != RESTART_NEEDED) - { - if (state == UP_TO_DATE){ - dbusmenu_menuitem_property_set (self->apt_item, - DBUSMENU_MENUITEM_PROP_LABEL, - _("Software Up to Date")); - if (self->reboot_query != 0){ - g_source_remove (self->reboot_query); - self->reboot_query = 0; - } - self->reboot_query = g_timeout_add_seconds (1, - apt_watcher_query_reboot_status, - self); - } - else if (state == UPDATES_AVAILABLE){ - dbusmenu_menuitem_property_set (self->apt_item, - DBUSMENU_MENUITEM_PROP_LABEL, - _("Updates Available…")); - } - else if (state == UPGRADE_IN_PROGRESS){ - dbusmenu_menuitem_property_set (self->apt_item, - DBUSMENU_MENUITEM_PROP_LABEL, - _("Updates Installing…")); - } - self->current_state = state; - } - if (self->current_state != UPGRADE_IN_PROGRESS){ - g_object_unref (G_OBJECT(self->current_transaction)); - self->current_transaction = NULL; - } -} - -static void -apt_watcher_manage_transactions (AptWatcher* self, gchar* transaction_id) +apt_watcher_init (AptWatcher *self) { - if (self->current_transaction == NULL){ - self->current_transaction = apt_transaction_new (transaction_id, SIMULATION); - g_signal_connect (G_OBJECT(self->current_transaction), - "state-update", - G_CALLBACK(apt_watcher_transaction_state_simulation_update_cb), self); - } + self->current_state = UP_TO_DATE; + g_timeout_add_seconds (60, + apt_watcher_start_apt_interaction, + self); } -static gboolean -apt_watcher_query_reboot_status (gpointer data) +static void +apt_watcher_finalize (GObject *object) { - g_return_val_if_fail (APT_IS_WATCHER (data), FALSE); - AptWatcher* self = APT_WATCHER (data); - - GVariant* reboot_result = g_dbus_proxy_get_cached_property (self->proxy, - "RebootRequired"); - gboolean reboot = FALSE; - g_variant_get (reboot_result, "b", &reboot); - g_debug ("apt_watcher_query_reboot_status: reboot prop = %i", reboot); - if (reboot == FALSE){ - dbusmenu_menuitem_property_set (self->apt_item, - DBUSMENU_MENUITEM_PROP_LABEL, - _("Software Up to Date")); - dbusmenu_menuitem_property_set (self->apt_item, - DBUSMENU_MENUITEM_PROP_DISPOSITION, - DBUSMENU_MENUITEM_DISPOSITION_NORMAL); - - } - else{ - dbusmenu_menuitem_property_set (self->apt_item, - DBUSMENU_MENUITEM_PROP_LABEL, - _("Restart to Complete Updates…")); - dbusmenu_menuitem_property_set (self->apt_item, - DBUSMENU_MENUITEM_PROP_DISPOSITION, - DBUSMENU_MENUITEM_DISPOSITION_ALERT); - session_dbus_restart_required (self->session_dbus_interface); - self->current_state = RESTART_NEEDED; - } - self->reboot_query = 0; - return FALSE; + g_bus_unwatch_name (watcher_id); + AptWatcher* self = APT_WATCHER (object); + + if (self->proxy != NULL) + g_object_unref (self->proxy); + + G_OBJECT_CLASS (apt_watcher_parent_class)->finalize (object); } -static void apt_watcher_signal_cb ( GDBusProxy* proxy, - gchar* sender_name, - gchar* signal_name, - GVariant* parameters, - gpointer user_data) +static void +apt_watcher_class_init (AptWatcherClass *klass) { - g_return_if_fail (APT_IS_WATCHER (user_data)); - AptWatcher* self = APT_WATCHER (user_data); - - g_variant_ref_sink (parameters); - GVariant *value = g_variant_get_child_value (parameters, 0); - - if (g_strcmp0(signal_name, "ActiveTransactionsChanged") == 0){ - gchar* current = NULL; - g_debug ("ActiveTransactionsChanged"); - - g_variant_get(value, "s", ¤t); - - if (g_str_has_prefix (current, "/org/debian/apt/transaction/") == TRUE){ - g_debug ("ActiveTransactionsChanged - current is %s", current); - - // Cancel all existing operations. - if (self->reboot_query != 0){ - g_source_remove (self->reboot_query); - self->reboot_query = 0; - } - - if (self->current_transaction != NULL) - { - g_object_unref (G_OBJECT(self->current_transaction)); - self->current_transaction = NULL; - } - - self->current_transaction = apt_transaction_new (current, REAL); - g_signal_connect (G_OBJECT(self->current_transaction), - "state-update", - G_CALLBACK(apt_watcher_transaction_state_real_update_cb), self); - } - } - else if (g_strcmp0(signal_name, "PropertyChanged") == 0) - { - gchar* prop_name= NULL; - GVariant* value = NULL; - g_variant_get (parameters, "(sv)", &prop_name, &value); - g_debug ("transaction prop update - prop = %s", prop_name); - - if (g_strcmp0 (prop_name, "RebootRequired") == 0){ - gboolean reboot_required = FALSE; - g_variant_get (value, "(b)", &reboot_required); - if (reboot_required){ - dbusmenu_menuitem_property_set (self->apt_item, - DBUSMENU_MENUITEM_PROP_LABEL, - _("Restart to Complete Updates…")); - dbusmenu_menuitem_property_set (self->apt_item, - DBUSMENU_MENUITEM_PROP_DISPOSITION, - DBUSMENU_MENUITEM_DISPOSITION_ALERT); - self->current_state = RESTART_NEEDED; - } - } - } - - g_variant_unref (value); - g_variant_unref (parameters); + GObjectClass* object_class = G_OBJECT_CLASS (klass); + object_class->finalize = apt_watcher_finalize; } AptWatcher* apt_watcher_new (SessionDbus* session_dbus, |