[gnome-settings-daemon] updates: port the gpk-update-icon update checking functionality
- From: Richard Hughes <rhughes src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-settings-daemon] updates: port the gpk-update-icon update checking functionality
- Date: Wed, 16 Feb 2011 21:48:40 +0000 (UTC)
commit 6d347b9f838383f452b070419faf4fcddd3f697a
Author: Richard Hughes <richard hughsie com>
Date: Wed Feb 16 21:44:16 2011 +0000
updates: port the gpk-update-icon update checking functionality
This provides libnotify messages if the user has not selected the updates
to be automatically installed. It does *not* provide a status icon.
I have also hooked up the distribution upgrades to present the user
a libnotify dialog if the option is selected by the admin in GSettings.
configure.ac | 2 +-
data/gsd-enums.h | 7 +
...ttings-daemon.plugins.updates.gschema.xml.in.in | 75 ++
plugins/updates/Makefile.am | 5 +
plugins/updates/gsd-updates-manager.c | 720 +++++++++++++++++++-
plugins/updates/gsd-updates-refresh.c | 629 +++++++++++++++++
plugins/updates/gsd-updates-refresh.h | 69 ++
po/POTFILES.in | 1 +
8 files changed, 1498 insertions(+), 10 deletions(-)
---
diff --git a/configure.ac b/configure.ac
index bcaf431..48c016a 100644
--- a/configure.ac
+++ b/configure.ac
@@ -281,7 +281,7 @@ AC_ARG_ENABLE(packagekit,
if test x$WANT_PACKAGEKIT = xyes ; then
PK_REQUIRED_VERSION=0.6.4
- PKG_CHECK_MODULES(PACKAGEKIT, glib-2.0 packagekit-glib2 >= $PK_REQUIRED_VERSION,
+ PKG_CHECK_MODULES(PACKAGEKIT, glib-2.0 packagekit-glib2 >= $PK_REQUIRED_VERSION upower-glib >= 0.9.1,
[have_packagekit=true
AC_DEFINE(HAVE_PACKAGEKIT, 1, [Define if PackageKit should be used])],
[have_packagekit=false])
diff --git a/data/gsd-enums.h b/data/gsd-enums.h
index c75f78d..59d2919 100644
--- a/data/gsd-enums.h
+++ b/data/gsd-enums.h
@@ -100,4 +100,11 @@ typedef enum
GSD_POWER_ACTION_NOTHING
} GsdPowerActionType;
+typedef enum
+{
+ GSD_UPDATE_TYPE_ALL,
+ GSD_UPDATE_TYPE_SECURITY,
+ GSD_UPDATE_TYPE_NONE
+} GsdUpdateType;
+
#endif /* __gsd_enums_h__ */
diff --git a/data/org.gnome.settings-daemon.plugins.updates.gschema.xml.in.in b/data/org.gnome.settings-daemon.plugins.updates.gschema.xml.in.in
index 2be6096..208f6cb 100644
--- a/data/org.gnome.settings-daemon.plugins.updates.gschema.xml.in.in
+++ b/data/org.gnome.settings-daemon.plugins.updates.gschema.xml.in.in
@@ -15,5 +15,80 @@
<_summary>The install root to use when adding and removing packages</_summary>
<_description>The install root to use when processing packages, which is changed when using LTSP or when testing.</_description>
</key>
+ <key name="connection-use-mobile" type="b">
+ <default>false</default>
+ <_summary>Use mobile broadband connections</_summary>
+ <_description>Use mobile broadband connections such as GSM and CDMA to check for updates.</_description>
+ </key>
+ <key name="connection-use-wifi" type="b">
+ <default>true</default>
+ <_summary>Use WiFi connections</_summary>
+ <_description>Use WiFi (wireless LAN) connections to check for updates. It may be faster to download packages when on a wired connection, and the VPN or proxy required may also only be available on wired connections.</_description>
+ </key>
+ <key name="auto-update-type" enum="org.gnome.settings-daemon.GsdUpdateType">
+ <default>'security'</default>
+ <_summary>Automatically update these types of updates</_summary>
+ <_description>Automatically update these types of updates.</_description>
+ </key>
+ <key name="force-get-updates-login" type="b">
+ <default>false</default>
+ <_summary>Get the update list when the session starts</_summary>
+ <_description>Get the update list when the session starts, even if not scheduled to. This ensures the user has up to date and valid data in the tray at startup.</_description>
+ </key>
+ <key name="frequency-get-updates" type="i">
+ <default>86400</default>
+ <_summary>How often to check for updates</_summary>
+ <_description>How often to check for updates. Value is in seconds.</_description>
+ </key>
+ <key name="frequency-get-upgrades" type="i">
+ <default>604800</default>
+ <_summary>How often to check for distribution upgrades</_summary>
+ <_description>How often to check for distribution upgrades. Value is in seconds.</_description>
+ </key>
+ <key name="frequency-refresh-cache" type="i">
+ <default>86400</default>
+ <_summary>How often to refresh the package cache</_summary>
+ <_description>How often to refresh the package cache. Value is in seconds.</_description>
+ </key>
+ <key name="session-startup-timeout" type="i">
+ <default>300</default>
+ <_summary>The number of seconds at session startup to wait before checking for updates</_summary>
+ <_description>The number of seconds at session startup to wait before checking for updates. Value is in seconds.</_description>
+ </key>
+ <key name="update-battery" type="b">
+ <default>false</default>
+ <_summary>Install updates automatically when running on battery power</_summary>
+ <_description>Install updates automatically when running on battery power.</_description>
+ </key>
+ <key name="notify-distro-upgrades" type="b">
+ <default>true</default>
+ <_summary>Notify the user when distribution upgrades are available</_summary>
+ <_description>Notify the user when distribution upgrades are available.</_description>
+ </key>
+ <key name="notify-update-complete" type="b">
+ <default>false</default>
+ <_summary>Notify the user for completed updates</_summary>
+ <_description>Notify the user for completed updates. This may be a useful notification for some users as installing updates prevents shutdown.</_description>
+ </key>
+ <key name="notify-update-complete-restart" type="b">
+ <default>true</default>
+ <_summary>Notify the user for completed updates where the user needs to restart</_summary>
+ <_description>Notify the user for completed updates where the user needs to restart.</_description>
+ </key>
+ <key name="notify-update-not-battery" type="b">
+ <default>false</default>
+ <_summary>Notify the user when the automatic update was not started on battery power</_summary>
+ <_description>Notify the user when the update was not automatically started because the machine is running on battery power.</_description>
+ </key>
+ <key name="notify-update-started" type="b">
+ <default>true</default>
+ <_summary>Notify the user when the update was started</_summary>
+ <_description>Notify the user when the update was started.</_description>
+ </key>
+ <key name="notify-update-type" enum="org.gnome.settings-daemon.GsdUpdateType">
+ <default>'security'</default>
+ <_summary>Notify the user when the update type is available</_summary>
+ <_description>Notify the user when updates are available of a certain type and not auto-installed.</_description>
+ </key>
</schema>
</schemalist>
diff --git a/plugins/updates/Makefile.am b/plugins/updates/Makefile.am
index fd00290..b06469a 100644
--- a/plugins/updates/Makefile.am
+++ b/plugins/updates/Makefile.am
@@ -4,6 +4,8 @@ plugin_LTLIBRARIES = \
libupdates_la_SOURCES = \
gsd-updates-plugin.h \
gsd-updates-plugin.c \
+ gsd-updates-refresh.h \
+ gsd-updates-refresh.c \
gsd-updates-manager.h \
gsd-updates-manager.c
@@ -17,6 +19,9 @@ libupdates_la_CFLAGS = \
$(GNOME_CFLAGS) \
$(PACKAGEKIT_CFLAGS) \
-DI_KNOW_THE_PACKAGEKIT_GLIB2_API_IS_SUBJECT_TO_CHANGE \
+ -DDATADIR=\"$(datadir)\" \
+ -DBINDIR=\"$(bindir)\" \
+ -I$(top_srcdir)/data \
$(AM_CFLAGS)
libupdates_la_LDFLAGS = \
diff --git a/plugins/updates/gsd-updates-manager.c b/plugins/updates/gsd-updates-manager.c
index 63b1918..038c3ea 100644
--- a/plugins/updates/gsd-updates-manager.c
+++ b/plugins/updates/gsd-updates-manager.c
@@ -25,33 +25,708 @@
#include <glib.h>
#include <glib/gi18n.h>
#include <gtk/gtk.h>
-
-#ifdef HAVE_PACKAGEKIT
#include <packagekit-glib2/packagekit.h>
-#endif
+#include <libnotify/notify.h>
+#include "gsd-enums.h"
#include "gsd-updates-manager.h"
+#include "gsd-updates-refresh.h"
#include "gnome-settings-profile.h"
#define GSD_UPDATES_MANAGER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GSD_TYPE_UPDATES_MANAGER, GsdUpdatesManagerPrivate))
struct GsdUpdatesManagerPrivate
{
- GSettings *settings_http;
- GSettings *settings_ftp;
- GSettings *settings_gsd;
- PkControl *control;
- guint timeout;
+ GCancellable *cancellable;
+ GsdUpdatesRefresh *refresh;
+ GSettings *settings_ftp;
+ GSettings *settings_gsd;
+ GSettings *settings_http;
+ guint number_updates_critical_last_shown;
+ guint timeout;
+ NotifyNotification *notification_updates_available;
+ PkControl *control;
+ PkTask *task;
};
static void gsd_updates_manager_class_init (GsdUpdatesManagerClass *klass);
static void gsd_updates_manager_init (GsdUpdatesManager *updates_manager);
static void gsd_updates_manager_finalize (GObject *object);
+static void update_packages_finished_cb (PkTask *task, GAsyncResult *res, GsdUpdatesManager *manager);
G_DEFINE_TYPE (GsdUpdatesManager, gsd_updates_manager, G_TYPE_OBJECT)
static gpointer manager_object = NULL;
+static void
+libnotify_action_cb (NotifyNotification *notification,
+ gchar *action,
+ gpointer user_data)
+{
+ gboolean ret;
+ GError *error = NULL;
+ GsdUpdatesManager *manager = GSD_UPDATES_MANAGER (user_data);
+
+ if (g_strcmp0 (action, "distro-upgrade-info") == 0) {
+ ret = g_spawn_command_line_async (DATADIR "/PackageKit/pk-upgrade-distro.sh",
+ &error);
+ if (!ret) {
+ g_warning ("Failure launching pk-upgrade-distro.sh: %s",
+ error->message);
+ g_error_free (error);
+ }
+ goto out;
+ }
+ if (g_strcmp0 (action, "show-update-viewer") == 0) {
+ ret = g_spawn_command_line_async (BINDIR "/gpk-update-viewer",
+ &error);
+ if (!ret) {
+ g_warning ("Failure launching update viewer: %s",
+ error->message);
+ g_error_free (error);
+ }
+ goto out;
+ }
+ if (g_strcmp0 (action, "update-all-packages") == 0) {
+ pk_task_update_system_async (manager->priv->task,
+ manager->priv->cancellable,
+ NULL, NULL,
+ (GAsyncReadyCallback) update_packages_finished_cb,
+ manager);
+ goto out;
+ }
+ if (g_strcmp0 (action, "cancel") == 0) {
+ /* try to cancel */
+ g_cancellable_cancel (manager->priv->cancellable);
+ goto out;
+ }
+ g_warning ("unknown action id: %s", action);
+out:
+ return;
+}
+
+static void
+get_distro_upgrades_finished_cb (GObject *object,
+ GAsyncResult *res,
+ GsdUpdatesManager *manager)
+{
+ const gchar *title;
+ gboolean ret;
+ gchar *name = NULL;
+ GError *error = NULL;
+ GPtrArray *array = NULL;
+ GString *string = NULL;
+ guint i;
+ NotifyNotification *notification;
+ PkClient *client = PK_CLIENT(object);
+ PkDistroUpgrade *item;
+ PkError *error_code = NULL;
+ PkResults *results;
+ PkUpdateStateEnum state;
+
+ /* get the results */
+ results = pk_client_generic_finish (PK_CLIENT(client), res, &error);
+ if (results == NULL) {
+ g_warning ("failed to get upgrades: %s",
+ error->message);
+ g_error_free (error);
+ goto out;
+ }
+
+ /* check error code */
+ error_code = pk_results_get_error_code (results);
+ if (error_code != NULL) {
+ g_warning ("failed to get upgrades: %s, %s",
+ pk_error_enum_to_text (pk_error_get_code (error_code)),
+ pk_error_get_details (error_code));
+ goto out;
+ }
+
+ /* process results */
+ array = pk_results_get_distro_upgrade_array (results);
+
+ /* any updates? */
+ if (array->len == 0) {
+ g_debug ("no upgrades");
+ goto out;
+ }
+
+ /* do we do the notification? */
+ ret = g_settings_get_boolean (manager->priv->settings_gsd,
+ GSD_SETTINGS_NOTIFY_DISTRO_UPGRADES);
+ if (!ret) {
+ g_debug ("ignoring due to GSettings");
+ goto out;
+ }
+
+ /* find the upgrade string */
+ string = g_string_new ("");
+ for (i=0; i < array->len; i++) {
+ item = (PkDistroUpgrade *) g_ptr_array_index (array, i);
+ g_object_get (item,
+ "name", &name,
+ "state", &state,
+ NULL);
+ g_string_append_printf (string, "%s (%s)\n",
+ name,
+ pk_distro_upgrade_enum_to_text (state));
+ g_free (name);
+ }
+ if (string->len != 0)
+ g_string_set_size (string, string->len-1);
+
+ /* TRANSLATORS: a distro update is available, e.g. Fedora 8 to Fedora 9 */
+ title = _("Distribution upgrades available");
+ notification = notify_notification_new (title, string->str, NULL);
+ if (notification == NULL) {
+ g_warning ("failed to create notification");
+ goto out;
+ }
+ notify_notification_set_timeout (notification, NOTIFY_EXPIRES_NEVER);
+ notify_notification_set_urgency (notification, NOTIFY_URGENCY_NORMAL);
+ notify_notification_add_action (notification, "distro-upgrade-info",
+ /* TRANSLATORS: provides more information about the upgrade */
+ _("More information"),
+ libnotify_action_cb,
+ manager, NULL);
+ ret = notify_notification_show (notification, &error);
+ if (!ret) {
+ g_warning ("error: %s", error->message);
+ g_error_free (error);
+ }
+out:
+ if (error_code != NULL)
+ g_object_unref (error_code);
+ if (array != NULL)
+ g_ptr_array_unref (array);
+ if (string != NULL)
+ g_string_free (string, TRUE);
+ if (results != NULL)
+ g_object_unref (results);
+}
+
+static void
+due_get_upgrades_cb (GsdUpdatesRefresh *refresh, GsdUpdatesManager *manager)
+{
+ /* optimize the amount of downloaded data by setting the cache age */
+ pk_client_set_cache_age (PK_CLIENT(manager->priv->task),
+ g_settings_get_int (manager->priv->settings_gsd,
+ GSD_SETTINGS_FREQUENCY_GET_UPGRADES));
+
+ /* get new distro upgrades list */
+ pk_client_get_distro_upgrades_async (PK_CLIENT(manager->priv->task),
+ NULL,
+ NULL, NULL,
+ (GAsyncReadyCallback) get_distro_upgrades_finished_cb,
+ manager);
+}
+
+static void
+refresh_cache_finished_cb (GObject *object, GAsyncResult *res, GsdUpdatesManager *manager)
+{
+ PkClient *client = PK_CLIENT(object);
+ PkResults *results;
+ GError *error = NULL;
+ PkError *error_code = NULL;
+
+ /* get the results */
+ results = pk_client_generic_finish (PK_CLIENT(client), res, &error);
+ if (results == NULL) {
+ g_warning ("failed to refresh the cache: %s",
+ error->message);
+ g_error_free (error);
+ goto out;
+ }
+
+ /* check error code */
+ error_code = pk_results_get_error_code (results);
+ if (error_code != NULL) {
+ g_warning ("failed to refresh the cache: %s, %s",
+ pk_error_enum_to_text (pk_error_get_code (error_code)),
+ pk_error_get_details (error_code));
+ goto out;
+ }
+out:
+ if (error_code != NULL)
+ g_object_unref (error_code);
+ if (results != NULL)
+ g_object_unref (results);
+}
+
+static void
+due_refresh_cache_cb (GsdUpdatesRefresh *refresh, GsdUpdatesManager *manager)
+{
+ /* optimize the amount of downloaded data by setting the cache age */
+ pk_client_set_cache_age (PK_CLIENT(manager->priv->task),
+ g_settings_get_int (manager->priv->settings_gsd,
+ GSD_SETTINGS_FREQUENCY_REFRESH_CACHE));
+
+ pk_client_refresh_cache_async (PK_CLIENT(manager->priv->task),
+ TRUE,
+ NULL,
+ NULL, NULL,
+ (GAsyncReadyCallback) refresh_cache_finished_cb,
+ manager);
+}
+
+static void
+notify_critical_updates (GsdUpdatesManager *manager, GPtrArray *array)
+{
+ const gchar *message;
+ const gchar *title;
+ gboolean ret;
+ GError *error = NULL;
+ GsdUpdateType update_type;
+ NotifyNotification *notification;
+
+ /* do we do the notification? */
+ update_type = g_settings_get_enum (manager->priv->settings_gsd,
+ GSD_SETTINGS_NOTIFY_UPDATE_TYPE);
+ if (update_type == GSD_UPDATE_TYPE_NONE) {
+ g_debug ("ignoring due to GSettings");
+ return;
+ }
+
+ /* if the number of critical updates is the same as the last notification,
+ * then skip the notifcation as we don't want to bombard the user every hour */
+ if (array->len == manager->priv->number_updates_critical_last_shown) {
+ g_debug ("ignoring as user ignored last warning");
+ return;
+ }
+
+ /* save for comparison later */
+ manager->priv->number_updates_critical_last_shown = array->len;
+
+ /* TRANSLATORS: title in the libnotify popup */
+ title = ngettext ("Security update available", "Security updates available", array->len);
+
+ /* TRANSLATORS: message when there are security updates */
+ message = ngettext ("An important update is available for your computer:",
+ "Important updates are available for your computer:", array->len);
+
+ /* close any existing notification */
+ if (manager->priv->notification_updates_available != NULL) {
+ notify_notification_close (manager->priv->notification_updates_available, NULL);
+ manager->priv->notification_updates_available = NULL;
+ }
+
+ /* do the bubble */
+ g_debug ("title=%s, message=%s", title, message);
+ notification = notify_notification_new (title, message, NULL);
+ if (notification == NULL) {
+ g_warning ("failed to get bubble");
+ return;
+ }
+ notify_notification_set_timeout (notification, 15000);
+ notify_notification_set_urgency (notification, NOTIFY_URGENCY_CRITICAL);
+ notify_notification_add_action (notification, "show-update-viewer",
+ /* TRANSLATORS: button: open the update viewer to install updates*/
+ _("Install updates"), libnotify_action_cb, manager, NULL);
+ ret = notify_notification_show (notification, &error);
+ if (!ret) {
+ g_warning ("error: %s", error->message);
+ g_error_free (error);
+ }
+ /* track so we can prevent doubled notifications */
+ manager->priv->notification_updates_available = notification;
+}
+
+static gboolean
+update_check_on_battery (GsdUpdatesManager *manager)
+{
+ const gchar *message;
+ gboolean ret;
+ GError *error = NULL;
+ NotifyNotification *notification;
+
+ ret = g_settings_get_boolean (manager->priv->settings_gsd,
+ GSD_SETTINGS_UPDATE_BATTERY);
+ if (ret) {
+ g_debug ("okay to update due to policy");
+ return TRUE;
+ }
+
+ ret = gsd_updates_refresh_get_on_battery (manager->priv->refresh);
+ if (!ret) {
+ g_debug ("okay to update as on AC");
+ return TRUE;
+ }
+
+ /* do we do the notification? */
+ ret = g_settings_get_boolean (manager->priv->settings_gsd,
+ GSD_SETTINGS_NOTIFY_UPDATE_NOT_BATTERY);
+ if (!ret) {
+ g_debug ("ignoring due to GSettings");
+ return FALSE;
+ }
+
+ /* TRANSLATORS: policy says update, but we are on battery and so prompt */
+ message = _("Automatic updates are not being installed as the computer is running on battery power");
+ /* TRANSLATORS: informs user will not install by default */
+ notification = notify_notification_new (_("Updates not installed"),
+ message, NULL);
+ notify_notification_set_timeout (notification, 15000);
+ notify_notification_set_urgency (notification, NOTIFY_URGENCY_LOW);
+ notify_notification_add_action (notification, "update-all-packages",
+ /* TRANSLATORS: to hell with my battery life, just do it */
+ _("Install the updates anyway"), libnotify_action_cb, manager, NULL);
+ ret = notify_notification_show (notification, &error);
+ if (!ret) {
+ g_warning ("error: %s", error->message);
+ g_error_free (error);
+ }
+
+ return FALSE;
+}
+
+static const gchar *
+restart_enum_to_localised_text (PkRestartEnum restart)
+{
+ const gchar *text = NULL;
+ switch (restart) {
+ case PK_RESTART_ENUM_NONE:
+ text = _("No restart is required.");
+ break;
+ case PK_RESTART_ENUM_SYSTEM:
+ text = _("A restart is required.");
+ break;
+ case PK_RESTART_ENUM_SESSION:
+ text = _("You need to log out and log back in.");
+ break;
+ case PK_RESTART_ENUM_APPLICATION:
+ text = _("You need to restart the application.");
+ break;
+ case PK_RESTART_ENUM_SECURITY_SESSION:
+ text = _("You need to log out and log back in to remain secure.");
+ break;
+ case PK_RESTART_ENUM_SECURITY_SYSTEM:
+ text = _("A restart is required to remain secure.");
+ break;
+ default:
+ g_warning ("restart unrecognised: %i", restart);
+ }
+ return text;
+}
+
+static void
+notify_update_finished (GsdUpdatesManager *manager, PkResults *results)
+{
+ const gchar *message;
+ gboolean ret;
+ gchar *package_id = NULL;
+ gchar **split;
+ gchar *summary = NULL;
+ GError *error = NULL;
+ GPtrArray *array;
+ GString *message_text = NULL;
+ guint i;
+ guint skipped_number = 0;
+ NotifyNotification *notification;
+ PkInfoEnum info;
+ PkPackage *item;
+ PkRestartEnum restart;
+
+ /* check we got some packages */
+ array = pk_results_get_package_array (results);
+ g_debug ("length=%i", array->len);
+ if (array->len == 0) {
+ g_debug ("no updates");
+ goto out;
+ }
+
+ message_text = g_string_new ("");
+
+ /* find any we skipped */
+ for (i=0; i<array->len; i++) {
+ item = g_ptr_array_index (array, i);
+ g_object_get (item,
+ "info", &info,
+ "package-id", &package_id,
+ "summary", &summary,
+ NULL);
+
+ split = pk_package_id_split (package_id);
+ g_debug ("%s, %s, %s", pk_info_enum_to_text (info),
+ split[PK_PACKAGE_ID_NAME], summary);
+ if (info == PK_INFO_ENUM_BLOCKED) {
+ skipped_number++;
+ g_string_append_printf (message_text, "<b>%s</b> - %s\n",
+ split[PK_PACKAGE_ID_NAME], summary);
+ }
+ g_free (package_id);
+ g_free (summary);
+ g_strfreev (split);
+ }
+
+ /* notify the user if there were skipped entries */
+ if (skipped_number > 0) {
+ /* TRANSLATORS: we did the update, but some updates were skipped and not applied */
+ message = ngettext ("One package was skipped:",
+ "Some packages were skipped:", skipped_number);
+ g_string_prepend (message_text, message);
+ g_string_append_c (message_text, '\n');
+ }
+
+ /* add a message that we need to restart */
+ restart = pk_results_get_require_restart_worst (results);
+ if (restart != PK_RESTART_ENUM_NONE) {
+ message = restart_enum_to_localised_text (restart);
+
+ /* add a gap if we are putting both */
+ if (skipped_number > 0)
+ g_string_append (message_text, "\n");
+
+ g_string_append (message_text, message);
+ g_string_append_c (message_text, '\n');
+ }
+
+ /* trim off extra newlines */
+ if (message_text->len != 0)
+ g_string_set_size (message_text, message_text->len-1);
+
+ /* do we do the notification? */
+ ret = g_settings_get_boolean (manager->priv->settings_gsd,
+ GSD_SETTINGS_NOTIFY_UPDATE_COMPLETE);
+ if (!ret) {
+ g_debug ("ignoring due to GSettings");
+ goto out;
+ }
+
+ /* TRANSLATORS: title: system update completed all okay */
+ notification = notify_notification_new (_("The system update has completed"),
+ message_text->str, NULL);
+ notify_notification_set_timeout (notification, 15000);
+ notify_notification_set_urgency (notification, NOTIFY_URGENCY_LOW);
+ if (restart == PK_RESTART_ENUM_SYSTEM) {
+ notify_notification_add_action (notification, "restart",
+ /* TRANSLATORS: restart computer as system packages need update */
+ _("Restart computer now"),
+ libnotify_action_cb,
+ manager, NULL);
+ }
+ ret = notify_notification_show (notification, &error);
+ if (!ret) {
+ g_warning ("error: %s", error->message);
+ g_error_free (error);
+ }
+out:
+ if (message_text != NULL)
+ g_string_free (message_text, TRUE);
+ if (array != NULL)
+ g_ptr_array_unref (array);
+}
+
+static void
+update_packages_finished_cb (PkTask *task,
+ GAsyncResult *res,
+ GsdUpdatesManager *manager)
+{
+ PkResults *results;
+ GError *error = NULL;
+ PkError *error_code = NULL;
+
+ /* get the results */
+ results = pk_task_generic_finish (task, res, &error);
+ if (results == NULL) {
+ g_warning ("failed to update system: %s",
+ error->message);
+ g_error_free (error);
+ goto out;
+ }
+
+ /* check error code */
+ error_code = pk_results_get_error_code (results);
+ if (error_code != NULL) {
+ g_warning ("failed to update system: %s, %s",
+ pk_error_enum_to_text (pk_error_get_code (error_code)),
+ pk_error_get_details (error_code));
+ goto out;
+ }
+
+ /* notify */
+ notify_update_finished (manager, results);
+ manager->priv->number_updates_critical_last_shown = 0;
+out:
+ if (error_code != NULL)
+ g_object_unref (error_code);
+ if (results != NULL)
+ g_object_unref (results);
+}
+
+static void
+notify_doing_updates (GsdUpdatesManager *manager)
+{
+ gboolean ret;
+ GError *error = NULL;
+ GsdUpdateType update_type;
+ NotifyNotification *notification;
+
+ /* in GSettings? */
+ update_type = g_settings_get_enum (manager->priv->settings_gsd,
+ GSD_SETTINGS_NOTIFY_UPDATE_TYPE);
+ if (update_type == GSD_UPDATE_TYPE_SECURITY ||
+ update_type == GSD_UPDATE_TYPE_NONE) {
+ g_debug ("ignoring due to GSettings");
+ goto out;
+ }
+
+ /* TRANSLATORS: title: notification when we scheduled an automatic update */
+ notification = notify_notification_new (_("Updates are being installed"),
+ /* TRANSLATORS: tell the user why the hard disk is grinding... */
+ _("Updates are being automatically installed on your computer"),
+ "software-update-urgent");
+ notify_notification_set_timeout (notification, 15000);
+ notify_notification_set_urgency (notification, NOTIFY_URGENCY_LOW);
+ /* TRANSLATORS: button: cancel the update system */
+ notify_notification_add_action (notification, "cancel",
+ _("Cancel update"),
+ libnotify_action_cb,
+ manager, NULL);
+ ret = notify_notification_show (notification, &error);
+ if (!ret) {
+ g_warning ("error: %s", error->message);
+ g_error_free (error);
+ }
+out:
+ return;
+}
+
+static void
+get_updates_finished_cb (GObject *object, GAsyncResult *res, GsdUpdatesManager *manager)
+{
+ PkClient *client = PK_CLIENT(object);
+ PkResults *results;
+ GError *error = NULL;
+ PkPackage *item;
+ guint i;
+ gboolean ret;
+ GsdUpdateType update;
+ GPtrArray *security_array = NULL;
+ gchar **package_ids;
+ GPtrArray *array = NULL;
+ PkError *error_code = NULL;
+
+ /* get the results */
+ results = pk_client_generic_finish (PK_CLIENT(client), res, &error);
+ if (results == NULL) {
+ g_warning ("failed to get updates: %s", error->message);
+ g_error_free (error);
+ goto out;
+ }
+
+ /* check error code */
+ error_code = pk_results_get_error_code (results);
+ if (error_code != NULL) {
+ g_warning ("failed to get updates: %s, %s",
+ pk_error_enum_to_text (pk_error_get_code (error_code)),
+ pk_error_get_details (error_code));
+ goto out;
+ }
+
+ /* get data */
+ array = pk_results_get_package_array (results);
+
+ /* we have no updates */
+ if (array->len == 0) {
+ g_debug ("no updates");
+ goto out;
+ }
+
+ /* we have updates to process */
+ security_array = g_ptr_array_new_with_free_func (g_free);
+
+ /* find the security updates first */
+ for (i=0; i<array->len; i++) {
+ item = g_ptr_array_index (array, i);
+ if (pk_package_get_info (item) != PK_INFO_ENUM_SECURITY)
+ continue;
+ g_ptr_array_add (security_array, g_strdup (pk_package_get_id (item)));
+ }
+
+ /* do we do the automatic updates? */
+ update = g_settings_get_enum (manager->priv->settings_gsd,
+ GSD_SETTINGS_AUTO_UPDATE_TYPE);
+
+ /* is policy none? */
+ if (update == GSD_UPDATE_TYPE_NONE) {
+ g_debug ("not updating as policy NONE");
+ /* do we warn the user? */
+ if (security_array->len > 0)
+ notify_critical_updates (manager, security_array);
+ goto out;
+ }
+
+ /* are we on battery and configured to skip the action */
+ ret = update_check_on_battery (manager);
+ if (!ret &&
+ ((update == GSD_UPDATE_TYPE_SECURITY && security_array->len > 0) ||
+ update == GSD_UPDATE_TYPE_ALL)) {
+ g_debug ("on battery so not doing update");
+ if (security_array->len > 0)
+ notify_critical_updates (manager, security_array);
+ goto out;
+ }
+
+ /* just do security updates */
+ if (update == GSD_UPDATE_TYPE_SECURITY) {
+ if (security_array->len == 0) {
+ g_debug ("policy security, but none available");
+ goto out;
+ }
+
+ /* convert */
+ package_ids = pk_ptr_array_to_strv (security_array);
+ pk_task_update_packages_async (manager->priv->task, package_ids,
+ manager->priv->cancellable,
+ NULL, NULL,
+ (GAsyncReadyCallback) update_packages_finished_cb, manager);
+ notify_doing_updates (manager);
+ g_strfreev (package_ids);
+ goto out;
+ }
+
+ /* just do everything */
+ if (update == GSD_UPDATE_TYPE_ALL) {
+ g_debug ("we should do the update automatically!");
+ pk_task_update_system_async (manager->priv->task,
+ manager->priv->cancellable,
+ NULL, NULL,
+ (GAsyncReadyCallback) update_packages_finished_cb,
+ manager);
+ notify_doing_updates (manager);
+ goto out;
+ }
+
+ /* shouldn't happen */
+ g_warning ("unknown update mode");
+out:
+ if (error_code != NULL)
+ g_object_unref (error_code);
+ if (security_array != NULL)
+ g_ptr_array_unref (security_array);
+ if (array != NULL)
+ g_ptr_array_unref (array);
+ if (results != NULL)
+ g_object_unref (results);
+}
+
+static void
+due_get_updates_cb (GsdUpdatesRefresh *refresh, GsdUpdatesManager *manager)
+{
+ /* optimize the amount of downloaded data by setting the cache age */
+ pk_client_set_cache_age (PK_CLIENT(manager->priv->task),
+ g_settings_get_int (manager->priv->settings_gsd,
+ GSD_SETTINGS_FREQUENCY_GET_UPDATES));
+
+ /* get new update list */
+ pk_client_get_updates_async (PK_CLIENT(manager->priv->task),
+ pk_bitfield_value (PK_FILTER_ENUM_NONE),
+ manager->priv->cancellable,
+ NULL, NULL,
+ (GAsyncReadyCallback) get_updates_finished_cb,
+ manager);
+}
+
static gchar *
get_proxy_http (GsdUpdatesManager *manager)
{
@@ -227,9 +902,24 @@ gboolean
gsd_updates_manager_start (GsdUpdatesManager *manager,
GError **error)
{
-
/* use PackageKit */
+ manager->priv->cancellable = g_cancellable_new ();
manager->priv->control = pk_control_new ();
+ manager->priv->task = pk_task_new ();
+ g_object_set (manager->priv->task,
+ "background", TRUE,
+ "interactive", FALSE,
+ NULL);
+
+ /* get automatic callbacks about when we should check for
+ * updates, refresh-caches and upgrades */
+ manager->priv->refresh = gsd_updates_refresh_new ();
+ g_signal_connect (manager->priv->refresh, "get-upgrades",
+ G_CALLBACK (due_get_upgrades_cb), manager);
+ g_signal_connect (manager->priv->refresh, "refresh-cache",
+ G_CALLBACK (due_refresh_cache_cb), manager);
+ g_signal_connect (manager->priv->refresh, "get-updates",
+ G_CALLBACK (due_get_updates_cb), manager);
/* get http settings */
manager->priv->settings_http = g_settings_new ("org.gnome.system.proxy.http");
@@ -276,6 +966,18 @@ gsd_updates_manager_stop (GsdUpdatesManager *manager)
g_object_unref (manager->priv->control);
manager->priv->control = NULL;
}
+ if (manager->priv->task != NULL) {
+ g_object_unref (manager->priv->task);
+ manager->priv->task = NULL;
+ }
+ if (manager->priv->refresh != NULL) {
+ g_object_unref (manager->priv->refresh);
+ manager->priv->refresh = NULL;
+ }
+ if (manager->priv->cancellable != NULL) {
+ g_object_unref (manager->priv->cancellable);
+ manager->priv->cancellable = NULL;
+ }
if (manager->priv->timeout) {
g_source_remove (manager->priv->timeout);
diff --git a/plugins/updates/gsd-updates-refresh.c b/plugins/updates/gsd-updates-refresh.c
new file mode 100644
index 0000000..9571df5
--- /dev/null
+++ b/plugins/updates/gsd-updates-refresh.c
@@ -0,0 +1,629 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2007-2011 Richard Hughes <richard hughsie com>
+ *
+ * Licensed under the GNU General Public License Version 2
+ *
+ * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "config.h"
+
+#include <glib/gi18n.h>
+#include <packagekit-glib2/packagekit.h>
+#include <libupower-glib/upower.h>
+
+#include "gsd-updates-refresh.h"
+
+static void gsd_updates_refresh_finalize (GObject *object);
+
+#define GSD_UPDATES_REFRESH_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GSD_TYPE_UPDATES_REFRESH, GsdUpdatesRefreshPrivate))
+
+#define PERIODIC_CHECK_TIME 60*60 /* poke PackageKit every hour */
+#define LOGIN_TIMEOUT 3 /* seconds */
+
+enum {
+ PRESENCE_STATUS_AVAILABLE = 0,
+ PRESENCE_STATUS_INVISIBLE,
+ PRESENCE_STATUS_BUSY,
+ PRESENCE_STATUS_IDLE,
+ PRESENCE_STATUS_UNKNOWN
+};
+
+/*
+ * at startup, after a small delay, force a GetUpdates call
+ * every hour (or any event) check:
+ - if we are online, idle and on AC power, it's been more than a day
+ since we refreshed then RefreshCache
+ - if we are online and it's been longer than the timeout since
+ getting the updates period then GetUpdates
+*/
+
+struct GsdUpdatesRefreshPrivate
+{
+ gboolean session_idle;
+ gboolean on_battery;
+ gboolean network_active;
+ gboolean force_get_updates_login;
+ guint force_get_updates_login_timeout_id;
+ guint timeout_id;
+ guint periodic_id;
+ UpClient *client;
+ GSettings *settings;
+ GDBusProxy *proxy_session;
+ PkControl *control;
+};
+
+enum {
+ REFRESH_CACHE,
+ GET_UPDATES,
+ GET_UPGRADES,
+ LAST_SIGNAL
+};
+
+static guint signals [LAST_SIGNAL] = { 0 };
+
+G_DEFINE_TYPE (GsdUpdatesRefresh, gsd_updates_refresh, G_TYPE_OBJECT)
+
+static void
+gsd_updates_refresh_class_init (GsdUpdatesRefreshClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ object_class->finalize = gsd_updates_refresh_finalize;
+ g_type_class_add_private (klass, sizeof (GsdUpdatesRefreshPrivate));
+ signals [REFRESH_CACHE] =
+ g_signal_new ("refresh-cache",
+ G_TYPE_FROM_CLASS (object_class), G_SIGNAL_RUN_LAST,
+ 0, NULL, NULL, g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE, 0);
+ signals [GET_UPDATES] =
+ g_signal_new ("get-updates",
+ G_TYPE_FROM_CLASS (object_class), G_SIGNAL_RUN_LAST,
+ 0, NULL, NULL, g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE, 0);
+ signals [GET_UPGRADES] =
+ g_signal_new ("get-upgrades",
+ G_TYPE_FROM_CLASS (object_class), G_SIGNAL_RUN_LAST,
+ 0, NULL, NULL, g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE, 0);
+}
+
+static void
+get_time_refresh_cache_cb (GObject *object,
+ GAsyncResult *res,
+ GsdUpdatesRefresh *refresh)
+{
+ PkControl *control = PK_CONTROL (object);
+ GError *error = NULL;
+ guint seconds;
+ guint thresh;
+
+ /* get the result */
+ seconds = pk_control_get_time_since_action_finish (control, res, &error);
+ if (seconds == 0) {
+ g_warning ("failed to get time: %s", error->message);
+ g_error_free (error);
+ return;
+ }
+
+ /* have we passed the timout? */
+ thresh = g_settings_get_int (refresh->priv->settings,
+ GSD_SETTINGS_FREQUENCY_GET_UPDATES);
+ if (seconds < thresh) {
+ g_debug ("not before timeout, thresh=%u, now=%u", thresh, seconds);
+ return;
+ }
+
+ /* send signal */
+ g_debug ("emitting refresh-cache");
+ g_signal_emit (refresh, signals [REFRESH_CACHE], 0);
+}
+
+static void
+maybe_refresh_cache (GsdUpdatesRefresh *refresh)
+{
+ guint thresh;
+
+ g_return_if_fail (GSD_IS_UPDATES_REFRESH (refresh));
+
+ /* if we don't want to auto check for updates, don't do this either */
+ thresh = g_settings_get_int (refresh->priv->settings,
+ GSD_SETTINGS_FREQUENCY_GET_UPDATES);
+ if (thresh == 0) {
+ g_debug ("not when policy is set to never");
+ return;
+ }
+
+ /* not on battery */
+ if (refresh->priv->on_battery) {
+ g_debug ("not when on battery");
+ return;
+ }
+
+ /* only do the refresh cache when the user is idle */
+ if (!refresh->priv->session_idle) {
+ g_debug ("not when session active");
+ return;
+ }
+
+ /* get this each time, as it may have changed behind out back */
+ thresh = g_settings_get_int (refresh->priv->settings,
+ GSD_SETTINGS_FREQUENCY_REFRESH_CACHE);
+ if (thresh == 0) {
+ g_debug ("not when policy is set to never");
+ return;
+ }
+
+ /* get the time since the last refresh */
+ pk_control_get_time_since_action_async (refresh->priv->control,
+ PK_ROLE_ENUM_REFRESH_CACHE,
+ NULL,
+ (GAsyncReadyCallback) get_time_refresh_cache_cb,
+ refresh);
+}
+
+static void
+get_time_get_updates_cb (GObject *object, GAsyncResult *res, GsdUpdatesRefresh *refresh)
+{
+ PkControl *control = PK_CONTROL (object);
+ GError *error = NULL;
+ guint seconds;
+ guint thresh;
+
+ /* get the result */
+ seconds = pk_control_get_time_since_action_finish (control, res, &error);
+ if (seconds == 0) {
+ g_warning ("failed to get time: %s", error->message);
+ g_error_free (error);
+ return;
+ }
+
+ /* have we passed the timout? */
+ thresh = g_settings_get_int (refresh->priv->settings,
+ GSD_SETTINGS_FREQUENCY_GET_UPDATES);
+ if (seconds < thresh) {
+ g_debug ("not before timeout, thresh=%u, now=%u", thresh, seconds);
+ return;
+ }
+
+ /* send signal */
+ g_debug ("emitting get-updates");
+ g_signal_emit (refresh, signals [GET_UPDATES], 0);
+}
+
+static void
+maybe_get_updates (GsdUpdatesRefresh *refresh)
+{
+ guint thresh;
+
+ g_return_if_fail (GSD_IS_UPDATES_REFRESH (refresh));
+
+ if (!refresh->priv->force_get_updates_login) {
+ refresh->priv->force_get_updates_login = TRUE;
+ if (g_settings_get_boolean (refresh->priv->settings,
+ GSD_SETTINGS_FORCE_GET_UPDATES_LOGIN)) {
+ g_debug ("forcing get update due to GSettings");
+ g_signal_emit (refresh, signals [GET_UPDATES], 0);
+ return;
+ }
+ }
+
+ /* if we don't want to auto check for updates, don't do this either */
+ thresh = g_settings_get_int (refresh->priv->settings,
+ GSD_SETTINGS_FREQUENCY_GET_UPDATES);
+ if (thresh == 0) {
+ g_debug ("not when policy is set to never");
+ return;
+ }
+
+ /* get the time since the last refresh */
+ pk_control_get_time_since_action_async (refresh->priv->control,
+ PK_ROLE_ENUM_GET_UPDATES,
+ NULL,
+ (GAsyncReadyCallback) get_time_get_updates_cb,
+ refresh);
+}
+
+static void
+get_time_get_upgrades_cb (GObject *object,
+ GAsyncResult *res,
+ GsdUpdatesRefresh *refresh)
+{
+ PkControl *control = PK_CONTROL (object);
+ GError *error = NULL;
+ guint seconds;
+ guint thresh;
+
+ /* get the result */
+ seconds = pk_control_get_time_since_action_finish (control, res, &error);
+ if (seconds == 0) {
+ g_warning ("failed to get time: %s", error->message);
+ g_error_free (error);
+ return;
+ }
+
+ /* have we passed the timout? */
+ thresh = g_settings_get_int (refresh->priv->settings,
+ GSD_SETTINGS_FREQUENCY_GET_UPDATES);
+ if (seconds < thresh) {
+ g_debug ("not before timeout, thresh=%u, now=%u",
+ thresh, seconds);
+ return;
+ }
+
+ /* send signal */
+ g_debug ("emitting get-upgrades");
+ g_signal_emit (refresh, signals [GET_UPGRADES], 0);
+}
+
+static void
+maybe_get_upgrades (GsdUpdatesRefresh *refresh)
+{
+ guint thresh;
+
+ g_return_if_fail (GSD_IS_UPDATES_REFRESH (refresh));
+
+ /* get this each time, as it may have changed behind out back */
+ thresh = g_settings_get_int (refresh->priv->settings,
+ GSD_SETTINGS_FREQUENCY_GET_UPGRADES);
+ if (thresh == 0) {
+ g_debug ("not when policy is set to never");
+ return;
+ }
+
+ /* get the time since the last refresh */
+ pk_control_get_time_since_action_async (refresh->priv->control,
+ PK_ROLE_ENUM_GET_DISTRO_UPGRADES,
+ NULL,
+ (GAsyncReadyCallback) get_time_get_upgrades_cb,
+ refresh);
+}
+
+static gboolean
+change_state_cb (GsdUpdatesRefresh *refresh)
+{
+ /* check all actions */
+ maybe_refresh_cache (refresh);
+ maybe_get_updates (refresh);
+ maybe_get_upgrades (refresh);
+ return FALSE;
+}
+
+static gboolean
+maybe_get_updates_logon_cb (GsdUpdatesRefresh *refresh)
+{
+ maybe_get_updates (refresh);
+ /* never repeat, even if failure */
+ return FALSE;
+}
+
+static gboolean
+change_state (GsdUpdatesRefresh *refresh)
+{
+ gboolean force;
+ guint value;
+
+ g_return_val_if_fail (GSD_IS_UPDATES_REFRESH (refresh), FALSE);
+
+ /* no point continuing if we have no network */
+ if (!refresh->priv->network_active) {
+ g_debug ("not when no network");
+ return FALSE;
+ }
+
+ /* only force a check if the user REALLY, REALLY wants to break
+ * set policy and have an update at startup */
+ if (!refresh->priv->force_get_updates_login) {
+ force = g_settings_get_boolean (refresh->priv->settings,
+ GSD_SETTINGS_FORCE_GET_UPDATES_LOGIN);
+ if (force) {
+ /* don't immediately send the signal, if we are
+ * called during object initialization
+ * we need to wait until upper layers finish
+ * hooking up to the signal first */
+ if (refresh->priv->force_get_updates_login_timeout_id == 0) {
+ refresh->priv->force_get_updates_login_timeout_id =
+ g_timeout_add_seconds (LOGIN_TIMEOUT,
+ (GSourceFunc) maybe_get_updates_logon_cb,
+ refresh);
+ g_source_set_name_by_id (refresh->priv->force_get_updates_login_timeout_id,
+ "[GsdUpdatesRefresh] maybe-get-updates");
+ }
+ }
+ }
+
+ /* wait a little time for things to settle down */
+ if (refresh->priv->timeout_id != 0)
+ g_source_remove (refresh->priv->timeout_id);
+ value = g_settings_get_int (refresh->priv->settings,
+ GSD_SETTINGS_SESSION_STARTUP_TIMEOUT);
+ g_debug ("defering action for %i seconds", value);
+ refresh->priv->timeout_id =
+ g_timeout_add_seconds (value, (GSourceFunc) change_state_cb, refresh);
+ g_source_set_name_by_id (refresh->priv->timeout_id,
+ "[GsdUpdatesRefresh] change-state");
+
+ return TRUE;
+}
+
+static void
+settings_key_changed_cb (GSettings *client,
+ const gchar *key,
+ GsdUpdatesRefresh *refresh)
+{
+ g_return_if_fail (GSD_IS_UPDATES_REFRESH (refresh));
+ if (g_strcmp0 (key, GSD_SETTINGS_SESSION_STARTUP_TIMEOUT) == 0 ||
+ g_strcmp0 (key, GSD_SETTINGS_FORCE_GET_UPDATES_LOGIN) == 0 ||
+ g_strcmp0 (key, GSD_SETTINGS_FREQUENCY_GET_UPDATES) == 0 ||
+ g_strcmp0 (key, GSD_SETTINGS_FREQUENCY_GET_UPGRADES) == 0 ||
+ g_strcmp0 (key, GSD_SETTINGS_FREQUENCY_REFRESH_CACHE) == 0 ||
+ g_strcmp0 (key, GSD_SETTINGS_AUTO_UPDATE_TYPE) == 0 ||
+ g_strcmp0 (key, GSD_SETTINGS_UPDATE_BATTERY) == 0)
+ change_state (refresh);
+}
+
+gboolean
+gsd_updates_refresh_get_on_battery (GsdUpdatesRefresh *refresh)
+{
+ g_return_val_if_fail (GSD_IS_UPDATES_REFRESH (refresh), FALSE);
+ return refresh->priv->on_battery;
+}
+
+static gboolean
+convert_network_state (GsdUpdatesRefresh *refresh, PkNetworkEnum state)
+{
+ /* offline */
+ if (state == PK_NETWORK_ENUM_OFFLINE)
+ return FALSE;
+
+ /* online */
+ if (state == PK_NETWORK_ENUM_ONLINE ||
+ state == PK_NETWORK_ENUM_WIRED)
+ return TRUE;
+
+ /* check policy */
+ if (state == PK_NETWORK_ENUM_MOBILE)
+ return g_settings_get_boolean (refresh->priv->settings,
+ GSD_SETTINGS_CONNECTION_USE_MOBILE);
+
+ /* check policy */
+ if (state == PK_NETWORK_ENUM_WIFI)
+ return g_settings_get_boolean (refresh->priv->settings,
+ GSD_SETTINGS_CONNECTION_USE_WIFI);
+
+ /* not recognised */
+ g_warning ("state unknown: %i", state);
+ return TRUE;
+}
+
+static void
+notify_network_state_cb (PkControl *control,
+ GParamSpec *pspec,
+ GsdUpdatesRefresh *refresh)
+{
+ PkNetworkEnum state;
+
+ g_return_if_fail (GSD_IS_UPDATES_REFRESH (refresh));
+
+ g_object_get (control, "network-state", &state, NULL);
+ refresh->priv->network_active = convert_network_state (refresh, state);
+ g_debug ("setting online %i", refresh->priv->network_active);
+ if (refresh->priv->network_active)
+ change_state (refresh);
+}
+
+static gboolean
+periodic_timeout_cb (gpointer user_data)
+{
+ GsdUpdatesRefresh *refresh = GSD_UPDATES_REFRESH (user_data);
+
+ g_return_val_if_fail (GSD_IS_UPDATES_REFRESH (refresh), FALSE);
+
+ /* debug so we can catch polling */
+ g_debug ("polling check");
+
+ /* triggered once an hour */
+ change_state (refresh);
+
+ /* always return */
+ return TRUE;
+}
+
+static void
+gsd_updates_refresh_client_changed_cb (UpClient *client,
+ GsdUpdatesRefresh *refresh)
+{
+ gboolean on_battery;
+
+ g_return_if_fail (GSD_IS_UPDATES_REFRESH (refresh));
+
+ /* get the on-battery state */
+ on_battery = up_client_get_on_battery (refresh->priv->client);
+ if (on_battery == refresh->priv->on_battery) {
+ g_debug ("same state as before, ignoring");
+ return;
+ }
+
+ /* save in local cache */
+ g_debug ("setting on_battery %i", on_battery);
+ refresh->priv->on_battery = on_battery;
+ if (!on_battery)
+ change_state (refresh);
+}
+
+static void
+get_properties_cb (GObject *object,
+ GAsyncResult *res,
+ GsdUpdatesRefresh *refresh)
+{
+ PkNetworkEnum state;
+ GError *error = NULL;
+ PkControl *control = PK_CONTROL(object);
+ gboolean ret;
+
+ /* get the result */
+ ret = pk_control_get_properties_finish (control, res, &error);
+ if (!ret) {
+ /* TRANSLATORS: backend is broken, and won't tell us what it supports */
+ g_warning ("could not get properties");
+ g_error_free (error);
+ goto out;
+ }
+
+ /* get values */
+ g_object_get (control,
+ "network-state", &state,
+ NULL);
+ refresh->priv->network_active = convert_network_state (refresh, state);
+out:
+ return;
+}
+
+static void
+session_presence_signal_cb (GDBusProxy *proxy,
+ gchar *sender_name,
+ gchar *signal_name,
+ GVariant *parameters,
+ GsdUpdatesRefresh *refresh)
+{
+ guint status;
+
+ g_return_if_fail (GSD_IS_UPDATES_REFRESH (refresh));
+
+ if (g_strcmp0 (signal_name, "StatusChanged") != 0)
+ return;
+
+ /* map stauts code into boolean */
+ g_variant_get (parameters, "(u)", &status);
+ refresh->priv->session_idle = (status == PRESENCE_STATUS_IDLE);
+ g_debug ("setting is_idle %i",
+ refresh->priv->session_idle);
+ if (refresh->priv->session_idle)
+ change_state (refresh);
+
+}
+
+static void
+gsd_updates_refresh_init (GsdUpdatesRefresh *refresh)
+{
+ GError *error = NULL;
+ GVariant *status;
+ guint status_code;
+
+ refresh->priv = GSD_UPDATES_REFRESH_GET_PRIVATE (refresh);
+ refresh->priv->on_battery = FALSE;
+ refresh->priv->network_active = FALSE;
+ refresh->priv->force_get_updates_login = FALSE;
+ refresh->priv->timeout_id = 0;
+ refresh->priv->periodic_id = 0;
+ refresh->priv->force_get_updates_login_timeout_id = 0;
+
+ /* we need to know the updates frequency */
+ refresh->priv->settings = g_settings_new (GSD_SETTINGS_SCHEMA);
+ g_signal_connect (refresh->priv->settings, "changed",
+ G_CALLBACK (settings_key_changed_cb), refresh);
+
+ /* we need to query the last cache refresh time */
+ refresh->priv->control = pk_control_new ();
+ g_signal_connect (refresh->priv->control, "notify::network-state",
+ G_CALLBACK (notify_network_state_cb),
+ refresh);
+
+ /* get network state */
+ pk_control_get_properties_async (refresh->priv->control,
+ NULL,
+ (GAsyncReadyCallback) get_properties_cb,
+ refresh);
+
+ /* use a UpClient */
+ refresh->priv->client = up_client_new ();
+ g_signal_connect (refresh->priv->client, "changed",
+ G_CALLBACK (gsd_updates_refresh_client_changed_cb), refresh);
+
+ /* get the battery state */
+ refresh->priv->on_battery = up_client_get_on_battery (refresh->priv->client);
+ g_debug ("setting on battery %i", refresh->priv->on_battery);
+
+ /* use gnome-session for the idle detection */
+ refresh->priv->proxy_session =
+ g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SESSION,
+ G_DBUS_PROXY_FLAGS_NONE,
+ NULL, /* GDBusInterfaceInfo */
+ "org.gnome.SessionManager",
+ "/org/gnome/SessionManager/Presence",
+ "org.gnome.SessionManager.Presence",
+ NULL, /* GCancellable */
+ &error);
+ if (refresh->priv->proxy_session == NULL) {
+ g_warning ("Error creating proxy: %s",
+ error->message);
+ g_error_free (error);
+ } else {
+ g_signal_connect (refresh->priv->proxy_session,
+ "g-signal",
+ G_CALLBACK (session_presence_signal_cb),
+ refresh);
+ status = g_dbus_proxy_get_cached_property (refresh->priv->proxy_session,
+ "status");
+ g_variant_get (status, "(u)", &status_code);
+ refresh->priv->session_idle = (status_code == PRESENCE_STATUS_IDLE);
+ g_variant_unref (status);
+ }
+
+ /* we check this in case we miss one of the async signals */
+ refresh->priv->periodic_id =
+ g_timeout_add_seconds (PERIODIC_CHECK_TIME,
+ periodic_timeout_cb, refresh);
+ g_source_set_name_by_id (refresh->priv->periodic_id,
+ "[GsdUpdatesRefresh] periodic check");
+
+ /* check system state */
+ change_state (refresh);
+}
+
+static void
+gsd_updates_refresh_finalize (GObject *object)
+{
+ GsdUpdatesRefresh *refresh;
+
+ g_return_if_fail (GSD_IS_UPDATES_REFRESH (object));
+
+ refresh = GSD_UPDATES_REFRESH (object);
+ g_return_if_fail (refresh->priv != NULL);
+
+ if (refresh->priv->timeout_id != 0)
+ g_source_remove (refresh->priv->timeout_id);
+ if (refresh->priv->periodic_id != 0)
+ g_source_remove (refresh->priv->periodic_id);
+ if (refresh->priv->force_get_updates_login_timeout_id != 0)
+ g_source_remove (refresh->priv->force_get_updates_login_timeout_id);
+
+ g_object_unref (refresh->priv->control);
+ g_object_unref (refresh->priv->settings);
+ g_object_unref (refresh->priv->client);
+ if (refresh->priv->proxy_session != NULL)
+ g_object_unref (refresh->priv->proxy_session);
+
+ G_OBJECT_CLASS (gsd_updates_refresh_parent_class)->finalize (object);
+}
+
+GsdUpdatesRefresh *
+gsd_updates_refresh_new (void)
+{
+ GsdUpdatesRefresh *refresh;
+ refresh = g_object_new (GSD_TYPE_UPDATES_REFRESH, NULL);
+ return GSD_UPDATES_REFRESH (refresh);
+}
+
diff --git a/plugins/updates/gsd-updates-refresh.h b/plugins/updates/gsd-updates-refresh.h
new file mode 100644
index 0000000..ad45dfe
--- /dev/null
+++ b/plugins/updates/gsd-updates-refresh.h
@@ -0,0 +1,69 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2007-2011 Richard Hughes <richard hughsie com>
+ *
+ * Licensed under the GNU General Public License Version 2
+ *
+ * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef __GSD_UPDATES_REFRESH_H
+#define __GSD_UPDATES_REFRESH_H
+
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+#define GSD_TYPE_UPDATES_REFRESH (gsd_updates_refresh_get_type ())
+#define GSD_UPDATES_REFRESH(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GSD_TYPE_UPDATES_REFRESH, GsdUpdatesRefresh))
+#define GSD_UPDATES_REFRESH_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), GSD_TYPE_UPDATES_REFRESH, GsdUpdatesRefreshClass))
+#define GSD_IS_UPDATES_REFRESH(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GSD_TYPE_UPDATES_REFRESH))
+
+typedef struct GsdUpdatesRefreshPrivate GsdUpdatesRefreshPrivate;
+
+typedef struct
+{
+ GObject parent;
+ GsdUpdatesRefreshPrivate *priv;
+} GsdUpdatesRefresh;
+
+typedef struct
+{
+ GObjectClass parent_class;
+} GsdUpdatesRefreshClass;
+
+#define GSD_SETTINGS_SCHEMA "org.gnome.settings-daemon.plugins.updates"
+#define GSD_SETTINGS_AUTO_UPDATE_TYPE "auto-update-type"
+#define GSD_SETTINGS_CONNECTION_USE_MOBILE "connection-use-mobile"
+#define GSD_SETTINGS_CONNECTION_USE_WIFI "connection-use-wifi"
+#define GSD_SETTINGS_FORCE_GET_UPDATES_LOGIN "force-get-updates-login"
+#define GSD_SETTINGS_FREQUENCY_GET_UPDATES "frequency-get-updates"
+#define GSD_SETTINGS_FREQUENCY_GET_UPGRADES "frequency-get-upgrades"
+#define GSD_SETTINGS_FREQUENCY_REFRESH_CACHE "frequency-refresh-cache"
+#define GSD_SETTINGS_NOTIFY_UPDATE_TYPE "notify-update-type"
+#define GSD_SETTINGS_NOTIFY_DISTRO_UPGRADES "notify-distro-upgrades"
+#define GSD_SETTINGS_NOTIFY_UPDATE_COMPLETE "notify-update-complete"
+#define GSD_SETTINGS_NOTIFY_UPDATE_COMPLETE_RESTART "notify-update-complete-restart"
+#define GSD_SETTINGS_NOTIFY_UPDATE_NOT_BATTERY "notify-update-not-battery"
+#define GSD_SETTINGS_SESSION_STARTUP_TIMEOUT "session-startup-timeout"
+#define GSD_SETTINGS_UPDATE_BATTERY "update-battery"
+
+GType gsd_updates_refresh_get_type (void);
+GsdUpdatesRefresh *gsd_updates_refresh_new (void);
+gboolean gsd_updates_refresh_get_on_battery (GsdUpdatesRefresh *refresh);
+
+G_END_DECLS
+
+#endif /* __GSD_UPDATES_REFRESH_H */
diff --git a/po/POTFILES.in b/po/POTFILES.in
index b896f80..4d18a83 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -46,3 +46,4 @@ plugins/xsettings/gsd-xsettings-manager.c
plugins/smartcard/gsd-smartcard-manager.c
plugins/smartcard/gsd-smartcard.c
plugins/datetime/org.gnome.settingsdaemon.datetimemechanism.policy.in
+plugins/updates/gsd-updates-manager.c
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]