diff options
-rw-r--r-- | client/gvfsiconloadable.c | 434 | ||||
-rw-r--r-- | common/Makefile.am | 2 | ||||
-rw-r--r-- | common/dbus-interfaces.xml | 3 | ||||
-rw-r--r-- | daemon/gvfsbackend.c | 1 | ||||
-rw-r--r-- | daemon/gvfsjobopenforread.c | 5 | ||||
-rw-r--r-- | daemon/gvfsjobopenforread.h | 1 | ||||
-rw-r--r-- | daemon/gvfsjobopeniconforread.c | 55 | ||||
-rw-r--r-- | daemon/gvfsjobopeniconforread.h | 9 |
8 files changed, 225 insertions, 285 deletions
diff --git a/client/gvfsiconloadable.c b/client/gvfsiconloadable.c index 2ca2d0fd..049eac8b 100644 --- a/client/gvfsiconloadable.c +++ b/client/gvfsiconloadable.c @@ -23,6 +23,7 @@ #include <config.h> #include <string.h> #include <glib/gi18n-lib.h> +#include <gio/gunixfdlist.h> #include "gvfsicon.h" #include "gvfsiconloadable.h" @@ -30,86 +31,51 @@ #include "gvfsdaemondbus.h" #include "gdaemonvfs.h" #include "gdaemonfileinputstream.h" -#include "gvfsdaemonprotocol.h" -#include "gvfsdbusutils.h" +#include <gvfsdbus.h> /* see comment in common/giconvfs.c for why the GLoadableIcon interface is here */ -static DBusMessage * -create_empty_message (GVfsIcon *vfs_icon, - const char *op, - GMountInfo **mount_info_out, - GError **error) + +static GVfsDBusMount * +create_proxy_for_icon (GVfsIcon *vfs_icon, + GCancellable *cancellable, + GError **error) { - DBusMessage *message; + GVfsDBusMount *proxy; GMountInfo *mount_info; + GDBusConnection *connection; + proxy = NULL; + mount_info = _g_daemon_vfs_get_mount_info_sync (vfs_icon->mount_spec, - "/", - error); - + "/", + cancellable, + error); + if (mount_info == NULL) - return NULL; - - if (mount_info_out) - *mount_info_out = g_mount_info_ref (mount_info); - - message = - dbus_message_new_method_call (mount_info->dbus_id, - mount_info->object_path, - G_VFS_DBUS_MOUNT_INTERFACE, - op); - - _g_dbus_message_append_args (message, G_DBUS_TYPE_CSTRING, &(vfs_icon->icon_id), 0); - - g_mount_info_unref (mount_info); - return message; -} - -static DBusMessage * -do_sync_path_call (GVfsIcon *vfs_icon, - const char *op, - GMountInfo **mount_info_out, - DBusConnection **connection_out, - GCancellable *cancellable, - GError **error, - int first_arg_type, - ...) -{ - DBusMessage *message, *reply; - va_list var_args; - GError *my_error; - - retry: - message = create_empty_message (vfs_icon, op, mount_info_out, error); - if (!message) - return NULL; - - va_start (var_args, first_arg_type); - _g_dbus_message_append_args_valist (message, - first_arg_type, - var_args); - va_end (var_args); - - - my_error = NULL; - reply = _g_vfs_daemon_call_sync (message, - connection_out, - NULL, NULL, NULL, - cancellable, &my_error); - dbus_message_unref (message); - - if (reply == NULL) - { - if (g_error_matches (my_error, G_VFS_ERROR, G_VFS_ERROR_RETRY)) - { - g_error_free (my_error); - goto retry; - } - g_propagate_error (error, my_error); - } + goto out; + + connection = _g_dbus_connection_get_sync (mount_info->dbus_id, cancellable, error); + if (connection == NULL) + goto out; + + proxy = gvfs_dbus_mount_proxy_new_sync (connection, + G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES | G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS, + mount_info->dbus_id, + mount_info->object_path, + cancellable, + error); + + if (proxy == NULL) + goto out; + + _g_dbus_connect_vfs_filters (connection); - return reply; + out: + if (mount_info) + g_mount_info_unref (mount_info); + + return proxy; } static GInputStream * @@ -119,170 +85,172 @@ g_vfs_icon_load (GLoadableIcon *icon, GCancellable *cancellable, GError **error) { - DBusConnection *connection; + GVfsIcon *vfs_icon = G_VFS_ICON (icon); + GVfsDBusMount *proxy; + gboolean res; + gboolean can_seek; + GUnixFDList *fd_list; int fd; - DBusMessage *reply; guint32 fd_id; - dbus_bool_t can_seek; - - reply = do_sync_path_call (G_VFS_ICON (icon), - G_VFS_DBUS_MOUNT_OP_OPEN_ICON_FOR_READ, - NULL, - &connection, - cancellable, - error, - 0); - if (reply == NULL) - return NULL; - if (!dbus_message_get_args (reply, NULL, - DBUS_TYPE_UINT32, &fd_id, - DBUS_TYPE_BOOLEAN, &can_seek, - DBUS_TYPE_INVALID)) - { - dbus_message_unref (reply); - g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, - _("Invalid return value from %s"), "open_icon_for_read"); - return NULL; - } + g_print ("gvfsiconloadable.c: g_vfs_icon_load\n"); - dbus_message_unref (reply); + proxy = create_proxy_for_icon (vfs_icon, cancellable, error); + if (proxy == NULL) + return NULL; + + res = gvfs_dbus_mount_call_open_icon_for_read_sync (proxy, + vfs_icon->icon_id, + NULL, + &fd_id, + &can_seek, + &fd_list, + cancellable, + error); + + g_print ("gvfsiconloadable.c: g_vfs_icon_load: done, res = %d\n", res); + + g_object_unref (proxy); - fd = _g_dbus_connection_get_fd_sync (connection, fd_id); - if (fd == -1) + if (! res) + return NULL; + + if (fd_list == NULL || g_unix_fd_list_get_length (fd_list) != 1 || + (fd = g_unix_fd_list_get (fd_list, 0, NULL)) == -1) { g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED, - _("Didn't get stream file descriptor")); + _("Didn't get stream file descriptor")); return NULL; } + g_object_unref (fd_list); + return G_INPUT_STREAM (g_daemon_file_input_stream_new (fd, can_seek)); } -typedef void (*AsyncPathCallCallback) (DBusMessage *reply, - DBusConnection *connection, - GSimpleAsyncResult *result, - GCancellable *cancellable, - gpointer callback_data); - +typedef void (*CreateProxyAsyncCallback) (GVfsDBusMount *proxy, + GSimpleAsyncResult *result, + GCancellable *cancellable, + gpointer callback_data); typedef struct { GSimpleAsyncResult *result; GVfsIcon *vfs_icon; - char *op; + GMountInfo *mount_info; + GDBusConnection *connection; + GVfsDBusMount *proxy; GCancellable *cancellable; - DBusMessage *args; - AsyncPathCallCallback callback; + CreateProxyAsyncCallback callback; gpointer callback_data; - GDestroyNotify notify; } AsyncPathCall; static void async_path_call_free (AsyncPathCall *data) { - if (data->notify) - data->notify (data->callback_data); - + if (data->connection) + g_object_unref (data->connection); + if (data->mount_info) + g_mount_info_unref (data->mount_info); if (data->result) g_object_unref (data->result); g_object_unref (data->vfs_icon); - g_free (data->op); if (data->cancellable) g_object_unref (data->cancellable); - if (data->args) - dbus_message_unref (data->args); + if (data->proxy) + g_object_unref (data->proxy); g_free (data); } static void -async_path_call_done (DBusMessage *reply, - DBusConnection *connection, - GError *io_error, - gpointer _data) +async_proxy_new_cb (GObject *source_object, + GAsyncResult *res, + gpointer user_data) { - AsyncPathCall *data = _data; - GSimpleAsyncResult *result; - - if (io_error != NULL) + AsyncPathCall *data = user_data; + GVfsDBusMount *proxy; + GError *error = NULL; + + proxy = gvfs_dbus_mount_proxy_new_finish (res, &error); + g_print ("gvfsiconloadable.c: async_proxy_new_cb, proxy = %p\n", proxy); + if (proxy == NULL) { - g_simple_async_result_set_from_error (data->result, io_error); + g_simple_async_result_take_error (data->result, error); _g_simple_async_result_complete_with_cancellable (data->result, data->cancellable); async_path_call_free (data); + return; } - else - { - result = data->result; - g_object_weak_ref (G_OBJECT (result), (GWeakNotify)async_path_call_free, data); - data->result = NULL; - - data->callback (reply, connection, - result, - data->cancellable, - data->callback_data); - - /* Free data here, or later if callback ref:ed the result */ - g_object_unref (result); - } + + data->proxy = proxy; + _g_dbus_connect_vfs_filters (data->connection); + + data->callback (proxy, + data->result, + data->cancellable, + data->callback_data); } static void -do_async_path_call_callback (GMountInfo *mount_info, - gpointer _data, - GError *error) +async_got_connection_cb (GDBusConnection *connection, + GError *io_error, + gpointer callback_data) { - AsyncPathCall *data = _data; - DBusMessage *message; - DBusMessageIter arg_source, arg_dest; + AsyncPathCall *data = callback_data; - if (error != NULL) + g_print ("gvfsiconloadable.c: async_got_connection_cb, connection = %p\n", connection); + + if (connection == NULL) { - g_simple_async_result_set_from_error (data->result, error); + g_simple_async_result_set_from_error (data->result, io_error); _g_simple_async_result_complete_with_cancellable (data->result, data->cancellable); async_path_call_free (data); return; } - - message = - dbus_message_new_method_call (mount_info->dbus_id, - mount_info->object_path, - G_VFS_DBUS_MOUNT_INTERFACE, - data->op); - _g_dbus_message_append_args (message, G_DBUS_TYPE_CSTRING, &(data->vfs_icon->icon_id), 0); + data->connection = g_object_ref (connection); + gvfs_dbus_mount_proxy_new (connection, + G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES | G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS, + data->mount_info->dbus_id, + data->mount_info->object_path, + data->cancellable, + async_proxy_new_cb, + data); +} - /* Append more args from data->args */ +static void +async_got_mount_info (GMountInfo *mount_info, + gpointer _data, + GError *error) +{ + AsyncPathCall *data = _data; + + g_print ("gvfsiconloadable.c: async_got_mount_info, mount_info = %p\n", mount_info); - if (data->args) + if (error != NULL) { - dbus_message_iter_init (data->args, &arg_source); - dbus_message_iter_init_append (message, &arg_dest); - - _g_dbus_message_iter_copy (&arg_dest, &arg_source); + g_simple_async_result_set_from_error (data->result, error); + _g_simple_async_result_complete_with_cancellable (data->result, data->cancellable); + async_path_call_free (data); + return; } - _g_vfs_daemon_call_async (message, - async_path_call_done, data, - data->cancellable); - - dbus_message_unref (message); -} + data->mount_info = g_mount_info_ref (mount_info); + _g_dbus_connection_get_for_async (mount_info->dbus_id, + async_got_connection_cb, + data, + data->cancellable); +} static void -do_async_path_call (GVfsIcon *vfs_icon, - const char *op, - GCancellable *cancellable, - GAsyncReadyCallback op_callback, - gpointer op_callback_data, - AsyncPathCallCallback callback, - gpointer callback_data, - GDestroyNotify notify, - int first_arg_type, - ...) +create_proxy_for_icon_async (GVfsIcon *vfs_icon, + GCancellable *cancellable, + GAsyncReadyCallback op_callback, + gpointer op_callback_data, + CreateProxyAsyncCallback callback, + gpointer callback_data) { - va_list var_args; AsyncPathCall *data; data = g_new0 (AsyncPathCall, 1); @@ -292,98 +260,73 @@ do_async_path_call (GVfsIcon *vfs_icon, NULL); data->vfs_icon = g_object_ref (vfs_icon); - data->op = g_strdup (op); if (cancellable) data->cancellable = g_object_ref (cancellable); data->callback = callback; data->callback_data = callback_data; - data->notify = notify; - - if (first_arg_type != 0) - { - data->args = dbus_message_new (DBUS_MESSAGE_TYPE_METHOD_CALL); - if (data->args == NULL) - _g_dbus_oom (); - - va_start (var_args, first_arg_type); - _g_dbus_message_append_args_valist (data->args, - first_arg_type, - var_args); - va_end (var_args); - } - - + _g_daemon_vfs_get_mount_info_async (vfs_icon->mount_spec, "/", - do_async_path_call_callback, + async_got_mount_info, data); } -typedef struct { - GSimpleAsyncResult *result; - GCancellable *cancellable; - gboolean can_seek; -} GetFDData; - static void -load_async_get_fd_cb (int fd, - gpointer callback_data) +open_icon_read_cb (GVfsDBusMount *proxy, + GAsyncResult *res, + gpointer user_data) { - GetFDData *data = callback_data; + AsyncPathCall *data = user_data; + GError *error = NULL; + gboolean can_seek; + GUnixFDList *fd_list; + int fd; + guint fd_id; GFileInputStream *stream; - if (fd == -1) + g_print ("gvfsiconloadable.c: open_icon_read_cb\n"); + + if (! gvfs_dbus_mount_call_open_icon_for_read_finish (proxy, &fd_id, &can_seek, &fd_list, res, &error)) + { + g_simple_async_result_take_error (data->result, error); + goto out; + } + + if (fd_list == NULL || g_unix_fd_list_get_length (fd_list) != 1 || + (fd = g_unix_fd_list_get (fd_list, fd_id, NULL)) == -1) { g_simple_async_result_set_error (data->result, - G_IO_ERROR, G_IO_ERROR_FAILED, - _("Couldn't get stream file descriptor")); + G_IO_ERROR, G_IO_ERROR_FAILED, + _("Couldn't get stream file descriptor")); } else { - stream = g_daemon_file_input_stream_new (fd, data->can_seek); + stream = g_daemon_file_input_stream_new (fd, can_seek); g_simple_async_result_set_op_res_gpointer (data->result, stream, g_object_unref); + g_object_unref (fd_list); } - _g_simple_async_result_complete_with_cancellable (data->result, - data->cancellable); - - g_object_unref (data->result); - if (data->cancellable) - g_object_unref (data->cancellable); - g_free (data); +out: + _g_simple_async_result_complete_with_cancellable (data->result, data->cancellable); + async_path_call_free (data); } static void -load_async_cb (DBusMessage *reply, - DBusConnection *connection, - GSimpleAsyncResult *result, - GCancellable *cancellable, - gpointer callback_data) +load_async_cb (GVfsDBusMount *proxy, + GSimpleAsyncResult *result, + GCancellable *cancellable, + gpointer callback_data) { - guint32 fd_id; - dbus_bool_t can_seek; - GetFDData *get_fd_data; + AsyncPathCall *data = callback_data; - if (!dbus_message_get_args (reply, NULL, - DBUS_TYPE_UINT32, &fd_id, - DBUS_TYPE_BOOLEAN, &can_seek, - DBUS_TYPE_INVALID)) - { - g_simple_async_result_set_error (result, - G_IO_ERROR, G_IO_ERROR_FAILED, - _("Invalid return value from %s"), "open"); - _g_simple_async_result_complete_with_cancellable (result, cancellable); - return; - } + g_print ("gvfsiconloadable.c: load_async_cb\n"); - get_fd_data = g_new0 (GetFDData, 1); - get_fd_data->result = g_object_ref (result); - if (cancellable) - get_fd_data->cancellable = g_object_ref (cancellable); - get_fd_data->can_seek = can_seek; - - _g_dbus_connection_get_fd_async (connection, fd_id, - load_async_get_fd_cb, get_fd_data); + gvfs_dbus_mount_call_open_icon_for_read (proxy, + data->vfs_icon->icon_id, + NULL, + cancellable, + (GAsyncReadyCallback) open_icon_read_cb, + callback_data); } static void @@ -393,12 +336,10 @@ g_vfs_icon_load_async (GLoadableIcon *icon, GAsyncReadyCallback callback, gpointer user_data) { - do_async_path_call (G_VFS_ICON (icon), - G_VFS_DBUS_MOUNT_OP_OPEN_ICON_FOR_READ, - cancellable, - callback, user_data, - load_async_cb, NULL, NULL, - 0); + create_proxy_for_icon_async (G_VFS_ICON (icon), + cancellable, + callback, user_data, + load_async_cb, NULL); } static GInputStream * @@ -417,7 +358,6 @@ g_vfs_icon_load_finish (GLoadableIcon *icon, return NULL; } - static void g_vfs_icon_loadable_icon_iface_init (GLoadableIconIface *iface) { diff --git a/common/Makefile.am b/common/Makefile.am index 4755711d..f7809680 100644 --- a/common/Makefile.am +++ b/common/Makefile.am @@ -20,6 +20,8 @@ $(dbus_built_sources) : Makefile.am dbus-interfaces.xml org.gtk.GDBus.C.UnixFD true \ --annotate "org.gtk.vfs.Mount.OpenForWrite()" \ org.gtk.GDBus.C.UnixFD true \ + --annotate "org.gtk.vfs.Mount.OpenIconForRead()" \ + org.gtk.GDBus.C.UnixFD true \ dbus-interfaces.xml \ $(NULL) diff --git a/common/dbus-interfaces.xml b/common/dbus-interfaces.xml index c3cfaac3..f80f9d77 100644 --- a/common/dbus-interfaces.xml +++ b/common/dbus-interfaces.xml @@ -319,6 +319,9 @@ <arg type='a(suu)' name='list' direction='out'/> </method> <method name="OpenIconForRead"> + <arg type='ay' name='path_data' direction='in'/> + <arg type='u' name='fd_id' direction='out'/> + <arg type='b' name='can_seek' direction='out'/> </method> </interface> diff --git a/daemon/gvfsbackend.c b/daemon/gvfsbackend.c index 8328ed2a..8f64b8e2 100644 --- a/daemon/gvfsbackend.c +++ b/daemon/gvfsbackend.c @@ -284,6 +284,7 @@ register_path_cb (GDBusConnection *conn, g_signal_connect (skeleton, "handle-pull", G_CALLBACK (g_vfs_job_pull_new_handle), data); g_signal_connect (skeleton, "handle-create-directory-monitor", G_CALLBACK (g_vfs_job_create_directory_monitor_new_handle), data); g_signal_connect (skeleton, "handle-create-file-monitor", G_CALLBACK (g_vfs_job_create_file_monitor_new_handle), data); + g_signal_connect (skeleton, "handle-open-icon-for-read", G_CALLBACK (g_vfs_job_open_icon_for_read_new_handle), data); error = NULL; if (!g_dbus_interface_skeleton_export (G_DBUS_INTERFACE_SKELETON (skeleton), diff --git a/daemon/gvfsjobopenforread.c b/daemon/gvfsjobopenforread.c index 75392339..95084c62 100644 --- a/daemon/gvfsjobopenforread.c +++ b/daemon/gvfsjobopenforread.c @@ -186,7 +186,10 @@ create_reply (GVfsJob *job, g_error_free (error); } - gvfs_dbus_mount_complete_open_for_read (object, invocation, fd_list, fd_id, open_job->can_seek); + if (open_job->read_icon) + gvfs_dbus_mount_complete_open_icon_for_read (object, invocation, fd_list, fd_id, open_job->can_seek); + else + gvfs_dbus_mount_complete_open_for_read (object, invocation, fd_list, fd_id, open_job->can_seek); /* FIXME: this could cause issues as long as fd_list closes all its fd's when it's finalized */ close (remote_fd); diff --git a/daemon/gvfsjobopenforread.h b/daemon/gvfsjobopenforread.h index 19f8321c..39d3da6b 100644 --- a/daemon/gvfsjobopenforread.h +++ b/daemon/gvfsjobopenforread.h @@ -47,6 +47,7 @@ struct _GVfsJobOpenForRead GVfsBackendHandle backend_handle; gboolean can_seek; GVfsReadChannel *read_channel; + gboolean read_icon; GPid pid; }; diff --git a/daemon/gvfsjobopeniconforread.c b/daemon/gvfsjobopeniconforread.c index a6a3d57d..603ffc7c 100644 --- a/daemon/gvfsjobopeniconforread.c +++ b/daemon/gvfsjobopeniconforread.c @@ -28,12 +28,10 @@ #include <sys/un.h> #include <glib.h> -#include <dbus/dbus.h> #include <glib/gi18n.h> +#include <gio/gunixfdlist.h> #include "gvfsreadchannel.h" #include "gvfsjobopeniconforread.h" -#include "gvfsdbusutils.h" -#include "gvfsdaemonutils.h" G_DEFINE_TYPE (GVfsJobOpenIconForRead, g_vfs_job_open_icon_for_read, G_VFS_TYPE_JOB_OPEN_FOR_READ) @@ -63,45 +61,36 @@ g_vfs_job_open_icon_for_read_init (GVfsJobOpenIconForRead *job) { } -GVfsJob * -g_vfs_job_open_icon_for_read_new (DBusConnection *connection, - DBusMessage *message, - GVfsBackend *backend) +gboolean +g_vfs_job_open_icon_for_read_new_handle (GVfsDBusMount *object, + GDBusMethodInvocation *invocation, + GUnixFDList *fd_list, + const gchar *arg_path_data, + GVfsBackend *backend) { GVfsJobOpenIconForRead *job; GVfsJobOpenForRead *job_open_for_read; - DBusMessage *reply; - DBusError derror; - int path_len; - const char *path_data; - - dbus_error_init (&derror); - if (!dbus_message_get_args (message, &derror, - DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, - &path_data, &path_len, - 0)) - { - reply = dbus_message_new_error (message, - derror.name, - derror.message); - dbus_error_free (&derror); - - dbus_connection_send (connection, reply, NULL); - dbus_message_unref (reply); - return NULL; - } + + g_print ("called OpenIconForRead()\n"); + if (g_vfs_backend_invocation_first_handler (object, invocation, backend)) + return TRUE; + job = g_object_new (G_VFS_TYPE_JOB_OPEN_ICON_FOR_READ, - "message", message, - "connection", connection, - NULL); - + "object", object, + "invocation", invocation, + NULL); + job_open_for_read = G_VFS_JOB_OPEN_FOR_READ (job); - job->icon_id = g_strndup (path_data, path_len); + job->icon_id = g_strdup (arg_path_data); job_open_for_read->backend = backend; + job_open_for_read->read_icon = TRUE; + + g_vfs_job_source_new_job (G_VFS_JOB_SOURCE (backend), G_VFS_JOB (job)); + g_object_unref (job); - return G_VFS_JOB (job); + return TRUE; } static void diff --git a/daemon/gvfsjobopeniconforread.h b/daemon/gvfsjobopeniconforread.h index 0f2bfd38..2096fe94 100644 --- a/daemon/gvfsjobopeniconforread.h +++ b/daemon/gvfsjobopeniconforread.h @@ -23,7 +23,6 @@ #ifndef __G_VFS_JOB_OPEN_ICON_FOR_READ_H__ #define __G_VFS_JOB_OPEN_ICON_FOR_READ_H__ -#include <dbus/dbus.h> #include <gvfsjobdbus.h> #include <gvfsbackend.h> #include <gvfsreadchannel.h> @@ -54,9 +53,11 @@ struct _GVfsJobOpenIconForReadClass GType g_vfs_job_open_icon_for_read_get_type (void) G_GNUC_CONST; -GVfsJob * g_vfs_job_open_icon_for_read_new (DBusConnection *connection, - DBusMessage *message, - GVfsBackend *backend); +gboolean g_vfs_job_open_icon_for_read_new_handle (GVfsDBusMount *object, + GDBusMethodInvocation *invocation, + GUnixFDList *fd_list, + const gchar *arg_path_data, + GVfsBackend *backend); G_END_DECLS |