[Spice-devel,spice-gtk,v2,04/16] file-xfer: introduce file-info signal

Submitted by Victor Toso on May 23, 2016, 11:50 a.m.

Details

Message ID 1464004253-17924-5-git-send-email-victortoso@redhat.com
State Superseded
Headers show
Series "separate SpiceFileTransferTask logic from channel-main" ( rev: 1 ) in Spice

Not browsing as part of any series.

Commit Message

Victor Toso May 23, 2016, 11:50 a.m.
In order to avoid sending the agent message on
file_xfer_info_async_cb, we can provide the "file-info" signal to
SpiceFileTransferTask.

In order to this signal be significant to applications, we request all
standard attributes to g_file_query_info_async.

This change is related to split SpiceFileTransferTask from
channel-main.
---
 src/channel-main.c | 96 ++++++++++++++++++++++++++++++++++++++----------------
 1 file changed, 68 insertions(+), 28 deletions(-)

Patch hide | download patch | download mbox

diff --git a/src/channel-main.c b/src/channel-main.c
index 0b355ba..6aaf96e 100644
--- a/src/channel-main.c
+++ b/src/channel-main.c
@@ -133,6 +133,7 @@  enum {
 
 enum {
     SIGNAL_FINISHED,
+    SIGNAL_FILE_INFO,
     LAST_TASK_SIGNAL
 };
 
@@ -2996,11 +2997,6 @@  static void file_xfer_info_async_cb(GObject *obj, GAsyncResult *res, gpointer da
     GFileInfo *info;
     GFile *file = G_FILE(obj);
     GError *error = NULL;
-    GKeyFile *keyfile = NULL;
-    gchar *basename = NULL;
-    VDAgentFileXferStartMessage msg;
-    gsize /*msg_size*/ data_len;
-    gchar *string;
     SpiceFileTransferTask *self = SPICE_FILE_TRANSFER_TASK(data);
 
     self->priv->pending = FALSE;
@@ -3010,33 +3006,14 @@  static void file_xfer_info_async_cb(GObject *obj, GAsyncResult *res, gpointer da
 
     self->priv->file_size =
         g_file_info_get_attribute_uint64(info, G_FILE_ATTRIBUTE_STANDARD_SIZE);
+    g_signal_emit(self, task_signals[SIGNAL_FILE_INFO], 0, info);
     g_object_notify(G_OBJECT(self), "progress");
-    keyfile = g_key_file_new();
+    g_clear_object(&info);
 
-    /* File name */
-    basename = g_file_get_basename(file);
-    g_key_file_set_string(keyfile, "vdagent-file-xfer", "name", basename);
-    g_free(basename);
-    /* File size */
-    g_key_file_set_uint64(keyfile, "vdagent-file-xfer", "size", self->priv->file_size);
-
-    /* Save keyfile content to memory. TODO: more file attributions
-       need to be sent to guest */
-    string = g_key_file_to_data(keyfile, &data_len, &error);
-    g_key_file_free(keyfile);
-    if (error)
-        goto failed;
-
-    /* Create file-xfer start message */
-    msg.id = self->priv->id;
-    agent_msg_queue_many(self->priv->channel, VD_AGENT_FILE_XFER_START,
-                         &msg, sizeof(msg),
-                         string, data_len + 1, NULL);
-    g_free(string);
-    spice_channel_wakeup(SPICE_CHANNEL(self->priv->channel), FALSE);
     return;
 
 failed:
+    g_clear_object(&info);
     spice_file_transfer_task_completed(self, error);
 }
 
@@ -3054,7 +3031,7 @@  static void file_xfer_read_async_cb(GObject *obj, GAsyncResult *res, gpointer da
     }
 
     g_file_query_info_async(self->priv->file,
-                            G_FILE_ATTRIBUTE_STANDARD_SIZE,
+                            "standard::*",
                             G_FILE_QUERY_INFO_NONE,
                             G_PRIORITY_DEFAULT,
                             self->priv->cancellable,
@@ -3066,6 +3043,50 @@  static void file_xfer_read_async_cb(GObject *obj, GAsyncResult *res, gpointer da
 static SpiceFileTransferTask *spice_file_transfer_task_new(SpiceMainChannel *channel,
                                                            GFile *file,
                                                            GCancellable *cancellable);
+static void file_xfer_on_file_info(SpiceFileTransferTask *xfer_task,
+                                   GFileInfo *info,
+                                   gpointer data)
+{
+    SpiceMainChannel *channel;
+    GKeyFile *keyfile;
+    VDAgentFileXferStartMessage msg;
+    gchar *string, *basename;
+    guint64 file_size;
+    gsize data_len;
+    GError *error = NULL;
+
+    g_return_if_fail(info != NULL);
+
+    channel = SPICE_MAIN_CHANNEL(data);
+
+    basename = g_file_info_get_attribute_as_string(info, G_FILE_ATTRIBUTE_STANDARD_NAME);
+    file_size = g_file_info_get_attribute_uint64(info, G_FILE_ATTRIBUTE_STANDARD_SIZE);
+
+    keyfile = g_key_file_new();
+    g_key_file_set_string(keyfile, "vdagent-file-xfer", "name", basename);
+    g_key_file_set_uint64(keyfile, "vdagent-file-xfer", "size", file_size);
+
+    g_free(basename);
+
+    /* Save keyfile content to memory. TODO: more file attributions
+       need to be sent to guest */
+    string = g_key_file_to_data(keyfile, &data_len, &error);
+    g_key_file_free(keyfile);
+    if (error)
+        goto failed;
+
+    /* Create file-xfer start message */
+    g_object_get(xfer_task, "id", &msg.id, NULL);
+    agent_msg_queue_many(channel, VD_AGENT_FILE_XFER_START,
+                         &msg, sizeof(msg),
+                         string, data_len + 1, NULL);
+    g_free(string);
+    spice_channel_wakeup(SPICE_CHANNEL(channel), FALSE);
+    return;
+
+failed:
+    spice_file_transfer_task_completed(xfer_task, error);
+}
 
 static void task_finished(SpiceFileTransferTask *task,
                           GError *error,
@@ -3154,6 +3175,7 @@  void spice_main_file_copy_async(SpiceMainChannel *channel,
 
         g_object_get(task, "id", &task_id, NULL);
         g_hash_table_insert(c->file_xfer_tasks, GUINT_TO_POINTER(task_id), task);
+        g_signal_connect(task, "file-info", G_CALLBACK(file_xfer_on_file_info), channel);
         g_signal_connect(task, "finished", G_CALLBACK(task_finished), channel);
         g_signal_emit(channel, signals[SPICE_MAIN_NEW_FILE_TRANSFER], 0, task);
         spice_file_transfer_task_start_task(task);
@@ -3477,6 +3499,24 @@  spice_file_transfer_task_class_init(SpiceFileTransferTaskClass *klass)
                                                         G_PARAM_STATIC_STRINGS));
 
     /**
+     * SpiceFileTransferTask::file-info
+     * @task: the file transfer task that emitted the signal
+     * @file_info: (transfer none): A GFileInfo object to retrieve file
+     * information. Only keys from standard namespace are supported.
+     *
+     * The #SpiceFileTransferTask::file-info signal is emitted just before the file
+     * transfer effectively starts.
+     *
+     * Since: 0.32
+     **/
+    task_signals[SIGNAL_FILE_INFO] = g_signal_new("file-info", SPICE_TYPE_FILE_TRANSFER_TASK,
+                                             G_SIGNAL_RUN_FIRST,
+                                             0, NULL, NULL,
+                                             g_cclosure_marshal_VOID__BOXED,
+                                             G_TYPE_NONE, 1,
+                                             G_TYPE_FILE_INFO);
+
+    /**
      * SpiceFileTransferTask::finished:
      * @task: the file transfer task that emitted the signal
      * @error: (transfer none): the error state of the transfer. Will be %NULL