[gnome-settings-daemon] updates: auto-download updates when possible, and add a DBus property for the shell to query



commit 2c083baae819e5ff24faa095e6f1c1f8bd0efcb6
Author: Richard Hughes <richard hughsie com>
Date:   Thu Mar 3 16:33:00 2011 +0000

    updates: auto-download updates when possible, and add a DBus property for the shell to query

 ...ttings-daemon.plugins.updates.gschema.xml.in.in |    5 +
 plugins/updates/Makefile.am                        |    3 +
 plugins/updates/gsd-updates-common.h               |    1 +
 plugins/updates/gsd-updates-manager.c              |  198 +++++++++++++++++++-
 .../updates/org.gnome.SettingsDaemonUpdates.xml    |   40 ++++
 5 files changed, 246 insertions(+), 1 deletions(-)
---
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 0cea787..67c551e 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
@@ -25,6 +25,11 @@
       <_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-download-updates" type="b">
+      <default>false</default>
+      <_summary>Automatically download updates in the background without confirmation</_summary>
+      <_description>Automatically download updates in the background without confirmation. Updates will be auto-downloaded when using wired network connnections, and also WiFi if 'connection-use-wifi' is enabled and mobile broadband if 'connection-use-mobile' is enabled.</_description>
+    </key>
     <key name="auto-update-type" enum="org.gnome.settings-daemon.GsdUpdateType">
       <default>'security'</default>
       <_summary>Automatically update these types of updates</_summary>
diff --git a/plugins/updates/Makefile.am b/plugins/updates/Makefile.am
index fcdf890..7d32a4a 100644
--- a/plugins/updates/Makefile.am
+++ b/plugins/updates/Makefile.am
@@ -1,3 +1,6 @@
+introspectiondir = $(datadir)/dbus-1/interfaces
+dist_introspection_DATA = org.gnome.SettingsDaemonUpdates.xml
+
 plugin_LTLIBRARIES = \
 	libupdates.la
 
diff --git a/plugins/updates/gsd-updates-common.h b/plugins/updates/gsd-updates-common.h
index 001a4ab..cb83bd0 100644
--- a/plugins/updates/gsd-updates-common.h
+++ b/plugins/updates/gsd-updates-common.h
@@ -44,6 +44,7 @@ G_BEGIN_DECLS
 #define GSD_SETTINGS_SCHEMA                             "org.gnome.settings-daemon.plugins.updates"
 #define GSD_SETTINGS_SESSION_STARTUP_TIMEOUT            "session-startup-timeout"
 #define GSD_SETTINGS_UPDATE_BATTERY                     "update-battery"
+#define GSD_SETTINGS_AUTO_DOWNLOAD_UPDATES              "auto-download-updates"
 
 G_END_DECLS
 
diff --git a/plugins/updates/gsd-updates-manager.c b/plugins/updates/gsd-updates-manager.c
index 009a6e5..d869712 100644
--- a/plugins/updates/gsd-updates-manager.c
+++ b/plugins/updates/gsd-updates-manager.c
@@ -57,12 +57,17 @@ struct GsdUpdatesManagerPrivate
         guint                    update_viewer_watcher_id;
         GVolumeMonitor          *volume_monitor;
         guint                    failed_get_updates_count;
+        gboolean                 pending_updates;
+        GDBusConnection         *connection;
+        guint                    owner_id;
+        GDBusNodeInfo           *introspection;
 };
 
 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);
+static void emit_changed (GsdUpdatesManager *manager);
 
 G_DEFINE_TYPE (GsdUpdatesManager, gsd_updates_manager, G_TYPE_OBJECT)
 
@@ -669,6 +674,72 @@ out:
 }
 
 static void
+package_download_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 download: %s",
+                           error->message);
+                g_error_free (error);
+                notify_failed_get_updates_maybe (manager);
+                goto out;
+        }
+
+        /* check error code */
+        error_code = pk_results_get_error_code (results);
+        if (error_code != NULL) {
+                g_warning ("failed to download: %s, %s",
+                           pk_error_enum_to_text (pk_error_get_code (error_code)),
+                           pk_error_get_details (error_code));
+                notify_failed_get_updates_maybe (manager);
+                goto out;
+        }
+
+        /* we succeeded, so allow the shell to query us */
+        manager->priv->pending_updates = TRUE;
+        emit_changed (manager);
+out:
+        if (error_code != NULL)
+                g_object_unref (error_code);
+        if (results != NULL)
+                g_object_unref (results);
+}
+
+static void
+auto_download_updates (GsdUpdatesManager *manager,
+                       GPtrArray *array)
+{
+        gchar **package_ids;
+        guint i;
+        PkPackage *pkg;
+
+        /* download each package */
+        package_ids = g_new0 (gchar *, array->len + 1);
+        for (i=0; i<array->len; i++) {
+                pkg = g_ptr_array_index (array, i);
+                package_ids[i] = g_strdup (pk_package_get_id (pkg));
+        }
+
+        /* download them all */
+        pk_client_download_packages_async (PK_CLIENT(manager->priv->task),
+                                           package_ids,
+                                           NULL, /* this means system cache */
+                                           manager->priv->cancellable,
+                                           NULL, NULL,
+                                           (GAsyncReadyCallback) package_download_finished_cb,
+                                           manager);
+        g_strfreev (package_ids);
+}
+
+static void
 get_updates_finished_cb (GObject *object,
                          GAsyncResult *res,
                          GsdUpdatesManager *manager)
@@ -740,6 +811,12 @@ get_updates_finished_cb (GObject *object,
                         notify_critical_updates (manager, security_array);
                 else
                         notify_normal_updates_maybe (manager, array);
+
+                /* should we auto-download other updates? */
+                ret = g_settings_get_boolean (manager->priv->settings_gsd,
+                                              GSD_SETTINGS_AUTO_DOWNLOAD_UPDATES);
+                if (ret)
+                        auto_download_updates (manager, array);
                 goto out;
         }
 
@@ -761,6 +838,9 @@ get_updates_finished_cb (GObject *object,
                         goto out;
                 }
 
+                /* even if this is TRUE, we're doing something about it */
+                manager->priv->pending_updates = FALSE;
+
                 /* convert */
                 package_ids = pk_ptr_array_to_strv (security_array);
                 pk_task_update_packages_async (manager->priv->task, package_ids,
@@ -773,6 +853,10 @@ get_updates_finished_cb (GObject *object,
 
         /* just do everything */
         if (update == GSD_UPDATE_TYPE_ALL) {
+
+                /* even if this is TRUE, we're doing something about it */
+                manager->priv->pending_updates = FALSE;
+
                 g_debug ("we should do the update automatically!");
                 pk_task_update_system_async (manager->priv->task,
                                              manager->priv->cancellable,
@@ -1157,11 +1241,95 @@ out:
         g_object_unref (root);
 }
 
+static void
+handle_method_call (GDBusConnection *connection_, const gchar *sender,
+                    const gchar *object_path, const gchar *interface_name,
+                    const gchar *method_name, GVariant *parameters,
+                    GDBusMethodInvocation *invocation, gpointer user_data)
+{
+        return;
+}
+
+static GVariant *
+handle_get_property (GDBusConnection *connection_, const gchar *sender,
+                     const gchar *object_path, const gchar *interface_name,
+                     const gchar *property_name, GError **error,
+                     gpointer user_data)
+{
+        GVariant *retval = NULL;
+        GsdUpdatesManager *manager = GSD_UPDATES_MANAGER(user_data);
+
+        if (g_strcmp0 (property_name, "PendingUpdates") == 0) {
+                retval = g_variant_new_boolean (manager->priv->pending_updates);
+        }
+
+        return retval;
+}
+
+static void
+on_bus_acquired (GDBusConnection *connection_, const gchar *name, gpointer user_data)
+{
+        guint registration_id;
+        GsdUpdatesManager *manager = GSD_UPDATES_MANAGER(user_data);
+        static const GDBusInterfaceVTable interface_vtable = {
+                handle_method_call,
+                handle_get_property,
+                NULL
+        };
+
+        registration_id = g_dbus_connection_register_object (connection_,
+                                                             "/",
+                                                             manager->priv->introspection->interfaces[0],
+                                                             &interface_vtable,
+                                                             NULL,  /* user_data */
+                                                             NULL,  /* user_data_free_func */
+                                                             NULL); /* GError** */
+        g_assert (registration_id > 0);
+}
+
+static void
+on_name_acquired (GDBusConnection *connection, const gchar *name, gpointer user_data)
+{
+        g_debug ("acquired name: %s", name);
+}
+
+static void
+on_name_lost (GDBusConnection *connection, const gchar *name, gpointer user_data)
+{
+        g_debug ("lost name: %s", name);
+}
+
+static void
+emit_changed (GsdUpdatesManager *manager)
+{
+        gboolean ret;
+        GError *error = NULL;
+
+        /* check we are connected */
+        if (manager->priv->connection == NULL)
+                return;
+
+        /* just emit signal */
+        ret = g_dbus_connection_emit_signal (manager->priv->connection,
+                                             NULL,
+                                             "/",
+                                             "org.gnome.SettingsDaemonUpdates",
+                                             "Changed",
+                                             NULL,
+                                             &error);
+        if (!ret) {
+                g_warning ("failed to emit signal: %s", error->message);
+                g_error_free (error);
+        }
+}
+
 gboolean
 gsd_updates_manager_start (GsdUpdatesManager *manager,
                            GError **error)
 {
         gboolean ret = FALSE;
+        gchar *introspection_data = NULL;
+        GFile *file = NULL;
 
         g_debug ("Starting updates manager");
 
@@ -1236,10 +1404,31 @@ gsd_updates_manager_start (GsdUpdatesManager *manager,
         reload_proxy_settings (manager);
         set_install_root (manager);
 
+        /* load introspection from file */
+        file = g_file_new_for_path (DATADIR "/dbus-1/interfaces/org.gnome.ColorManager.xml");
+        ret = g_file_load_contents (file, NULL, &introspection_data, NULL, NULL, error);
+        if (!ret)
+                goto out;
+
+        /* build introspection from XML */
+        manager->priv->introspection = g_dbus_node_info_new_for_xml (introspection_data, error);
+        if (manager->priv->introspection == NULL)
+                goto out;
+
+        /* own the object */
+        manager->priv->owner_id = g_bus_own_name (G_BUS_TYPE_SESSION,
+                                                  "org.gnome.SettingsDaemonUpdates",
+                                                  G_BUS_NAME_OWNER_FLAGS_NONE,
+                                                  on_bus_acquired,
+                                                  on_name_acquired,
+                                                  on_name_lost,
+                                                  manager, NULL);
+
         /* success */
         ret = TRUE;
         g_debug ("Started updates manager");
 out:
+        g_free (introspection_data);
         return ret;
 }
 
@@ -1288,11 +1477,18 @@ gsd_updates_manager_stop (GsdUpdatesManager *manager)
                 g_object_unref (manager->priv->cancellable);
                 manager->priv->cancellable = NULL;
         }
+        if (manager->priv->introspection != NULL) {
+                g_dbus_node_info_unref (manager->priv->introspection);
+                manager->priv->introspection = NULL;
+        }
         if (manager->priv->update_viewer_watcher_id != 0) {
                 g_bus_unwatch_name (manager->priv->update_viewer_watcher_id);
                 manager->priv->update_viewer_watcher_id = 0;
         }
-
+        if (manager->priv->owner_id > 0) {
+                g_bus_unown_name (manager->priv->owner_id);
+                manager->priv->owner_id = 0;
+        }
         if (manager->priv->timeout) {
                 g_source_remove (manager->priv->timeout);
                 manager->priv->timeout = 0;
diff --git a/plugins/updates/org.gnome.SettingsDaemonUpdates.xml b/plugins/updates/org.gnome.SettingsDaemonUpdates.xml
new file mode 100644
index 0000000..c4fbb2b
--- /dev/null
+++ b/plugins/updates/org.gnome.SettingsDaemonUpdates.xml
@@ -0,0 +1,40 @@
+<!DOCTYPE node PUBLIC
+'-//freedesktop//DTD D-BUS Object Introspection 1.0//EN'
+'http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd'>
+<node>
+  <interface name='org.gnome.SettingsDaemonUpdates'>
+    <doc:doc>
+      <doc:description>
+        <doc:para>
+          The interface used for quering trivial information about the
+          update plugin in gnome-settings-daemon.
+        </doc:para>
+      </doc:description>
+    </doc:doc>
+
+    <!--*****************************************************************************************-->
+    <property name='PendingUpdates' type='b' access='read'>
+      <doc:doc>
+        <doc:description>
+          <doc:para>
+            If there are updates that have been downloaded and are waiting
+            to be applied.
+          </doc:para>
+        </doc:description>
+      </doc:doc>
+    </property>
+
+    <!-- ************************************************************ -->
+    <signal name='Changed'>
+      <doc:doc>
+        <doc:description>
+          <doc:para>
+            Some value on the interface has changed.
+          </doc:para>
+        </doc:description>
+      </doc:doc>
+    </signal>
+
+  </interface>
+</node>
+



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]