diff options
Diffstat (limited to 'common')
-rw-r--r-- | common/gmountoperationdbus.c | 89 | ||||
-rw-r--r-- | common/gmountsource.c | 254 | ||||
-rw-r--r-- | common/gmountsource.h | 25 | ||||
-rw-r--r-- | common/gvfsdaemonprotocol.h | 2 |
4 files changed, 366 insertions, 4 deletions
diff --git a/common/gmountoperationdbus.c b/common/gmountoperationdbus.c index b8ac4f7d..9122042e 100644 --- a/common/gmountoperationdbus.c +++ b/common/gmountoperationdbus.c @@ -51,6 +51,8 @@ static void mount_op_ask_password (GMountOperationDBus *op_d DBusMessage *message); static void mount_op_ask_question (GMountOperationDBus *op_dbus, DBusMessage *message); +static void mount_op_show_processes (GMountOperationDBus *op_dbus, + DBusMessage *message); static void mount_op_aborted (GMountOperationDBus *op_dbus, DBusMessage *message); @@ -135,6 +137,10 @@ mount_op_message_function (DBusConnection *connection, mount_op_ask_question (op_dbus, message); else if (dbus_message_is_method_call (message, G_VFS_DBUS_MOUNT_OPERATION_INTERFACE, + G_VFS_DBUS_MOUNT_OPERATION_OP_SHOW_PROCESSES)) + mount_op_show_processes (op_dbus, message); + else if (dbus_message_is_method_call (message, + G_VFS_DBUS_MOUNT_OPERATION_INTERFACE, G_VFS_DBUS_MOUNT_OPERATION_OP_ABORTED)) mount_op_aborted (op_dbus, message); else @@ -320,8 +326,91 @@ mount_op_ask_question (GMountOperationDBus *op_dbus, } static void +show_processes_reply (GMountOperation *op, + GMountOperationResult result, + gpointer data) +{ + DBusMessage *reply = data; + guint32 choice; + dbus_bool_t handled, abort_dbus; + GMountOperationDBus *op_dbus; + + op_dbus = g_object_get_data (G_OBJECT (op), "dbus-op"); + + handled = (result != G_MOUNT_OPERATION_UNHANDLED); + abort_dbus = (result == G_MOUNT_OPERATION_ABORTED); + + choice = g_mount_operation_get_choice (op); + + _g_dbus_message_append_args (reply, + DBUS_TYPE_BOOLEAN, &handled, + DBUS_TYPE_BOOLEAN, &abort_dbus, + DBUS_TYPE_UINT32, &choice, + 0); + + mount_op_send_reply (op_dbus, reply); +} + +static void +mount_op_show_processes (GMountOperationDBus *op_dbus, + DBusMessage *message) +{ + const char *message_string; + char **choices; + int num_choices; + gint32 **process_pids; + int num_process_pids; + DBusMessage *reply; + DBusError error; + DBusMessageIter iter; + GArray *processes; + + reply = NULL; + + dbus_message_iter_init (message, &iter); + dbus_error_init (&error); + if (!_g_dbus_message_iter_get_args (&iter, + &error, + DBUS_TYPE_STRING, &message_string, + DBUS_TYPE_ARRAY, DBUS_TYPE_STRING, + &choices, &num_choices, + DBUS_TYPE_ARRAY, DBUS_TYPE_INT32, + &process_pids, &num_process_pids, + 0)) + { + reply = dbus_message_new_error (message, error.name, error.message); + if (reply == NULL) + _g_dbus_oom (); + if (!dbus_connection_send (op_dbus->connection, reply, NULL)) + _g_dbus_oom (); + dbus_message_unref (reply); + dbus_error_free (&error); + return; + } + + processes = g_array_sized_new (FALSE, FALSE, sizeof (GPid), num_process_pids); + g_array_append_vals (processes, process_pids, num_process_pids); + + reply = dbus_message_new_method_return (message); + if (reply == NULL) + _g_dbus_oom (); + + g_signal_connect (op_dbus->op, "reply", (GCallback)show_processes_reply, reply); + + g_signal_emit_by_name (op_dbus->op, "show_processes", + message_string, + processes, + choices); + + dbus_free_string_array (choices); + g_array_unref (processes); +} + +static void mount_op_aborted (GMountOperationDBus *op_dbus, DBusMessage *message) { + /* also emit reply to make the all DBus ops return */ + g_mount_operation_reply (op_dbus->op, G_MOUNT_OPERATION_UNHANDLED); g_signal_emit_by_name (op_dbus->op, "aborted"); } diff --git a/common/gmountsource.c b/common/gmountsource.c index ac705fad..5ee964ea 100644 --- a/common/gmountsource.c +++ b/common/gmountsource.c @@ -699,12 +699,241 @@ op_ask_question (GMountOperation *op, return TRUE; } +typedef struct ShowProcessesData ShowProcessesData; + +struct ShowProcessesData { + + /* results: */ + gboolean aborted; + guint32 choice; +}; + +/* the callback from dbus -> main thread */ +static void +show_processes_reply (DBusMessage *reply, + GError *error, + gpointer _data) +{ + GSimpleAsyncResult *result; + ShowProcessesData *data; + dbus_bool_t handled, aborted; + guint32 choice; + DBusMessageIter iter; + + result = G_SIMPLE_ASYNC_RESULT (_data); + handled = TRUE; + + data = g_new0 (ShowProcessesData, 1); + g_simple_async_result_set_op_res_gpointer (result, data, g_free); + + if (reply == NULL) + { + data->aborted = TRUE; + } + else + { + dbus_message_iter_init (reply, &iter); + if (!_g_dbus_message_iter_get_args (&iter, NULL, + DBUS_TYPE_BOOLEAN, &handled, + DBUS_TYPE_BOOLEAN, &aborted, + DBUS_TYPE_UINT32, &choice, + 0)) + data->aborted = TRUE; + else + { + data->aborted = aborted; + data->choice = choice; + } + } + + if (handled == FALSE) + { + g_simple_async_result_set_error (result, G_IO_ERROR, G_IO_ERROR_FAILED, "Internal Error"); + } + + g_simple_async_result_complete (result); +} + +void +g_mount_source_show_processes_async (GMountSource *source, + const char *message_string, + GArray *processes, + const char **choices, + gint n_choices, + GAsyncReadyCallback callback, + gpointer user_data) +{ + GSimpleAsyncResult *result; + DBusMessage *message; + + /* If no dbus id specified, reply that we weren't handled */ + if (source->dbus_id[0] == 0) + { + g_simple_async_report_error_in_idle (G_OBJECT (source), + callback, + user_data, + G_IO_ERROR, G_IO_ERROR_FAILED, + "Internal Error"); + return; + } + + result = g_simple_async_result_new (G_OBJECT (source), callback, user_data, + g_mount_source_show_processes_async); + + if (message_string == NULL) + message_string = ""; + + message = dbus_message_new_method_call (source->dbus_id, + source->obj_path, + G_VFS_DBUS_MOUNT_OPERATION_INTERFACE, + G_VFS_DBUS_MOUNT_OPERATION_OP_SHOW_PROCESSES); + + _g_dbus_message_append_args (message, + DBUS_TYPE_STRING, &message_string, + DBUS_TYPE_ARRAY, DBUS_TYPE_STRING, + &choices, n_choices, + DBUS_TYPE_ARRAY, DBUS_TYPE_INT32, + &processes->data, processes->len, + 0); + + /* 30 minute timeout */ + _g_dbus_connection_call_async (NULL, message, 1000 * 60 * 30, + show_processes_reply, result); + dbus_message_unref (message); +} + +gboolean +g_mount_source_show_processes_finish (GMountSource *source, + GAsyncResult *result, + gboolean *aborted, + gint *choice_out) +{ + ShowProcessesData *data, def= { FALSE, }; + GSimpleAsyncResult *simple; + + simple = G_SIMPLE_ASYNC_RESULT (result); + + if (g_simple_async_result_propagate_error (simple, NULL)) + data = &def; + else + data = (ShowProcessesData *) g_simple_async_result_get_op_res_gpointer (simple); + + if (aborted) + *aborted = data->aborted; + + if (choice_out) + *choice_out = data->choice; + + return data != &def; +} + +gboolean +g_mount_source_show_processes (GMountSource *source, + const char *message, + GArray *processes, + const char **choices, + gint n_choices, + gboolean *aborted_out, + gint *choice_out) +{ + gint choice; + gboolean handled, aborted; + AskSyncData data = {NULL}; + + data.mutex = g_mutex_new (); + data.cond = g_cond_new (); + + g_mutex_lock (data.mutex); + + g_mount_source_show_processes_async (source, + message, + processes, + choices, + n_choices, + ask_reply_sync, + &data); + + g_cond_wait (data.cond, data.mutex); + g_mutex_unlock (data.mutex); + + g_cond_free (data.cond); + g_mutex_free (data.mutex); + + handled = g_mount_source_show_processes_finish (source, + data.result, + &aborted, + &choice); + + g_object_unref (data.result); + + if (aborted_out) + *aborted_out = aborted; + + if (choice_out) + *choice_out = choice; + + return handled; +} + +static void +op_show_processes_reply (GObject *source_object, + GAsyncResult *res, + gpointer user_data) +{ + GMountOperationResult result; + GMountOperation *op; + GMountSource *source; + gboolean handled, aborted; + gint choice; + + source = G_MOUNT_SOURCE (source_object); + op = G_MOUNT_OPERATION (user_data); + + handled = g_mount_source_show_processes_finish (source, + res, + &aborted, + &choice); + + if (!handled) + result = G_MOUNT_OPERATION_UNHANDLED; + else if (aborted) + result = G_MOUNT_OPERATION_ABORTED; + else + { + result = G_MOUNT_OPERATION_HANDLED; + g_mount_operation_set_choice (op, choice); + } + + g_mount_operation_reply (op, result); + g_object_unref (op); +} + static gboolean -op_aborted (GMountOperation *op, - GMountSource *source) +op_show_processes (GMountOperation *op, + const char *message, + GArray *processes, + const char **choices, + GMountSource *mount_source) +{ + g_mount_source_show_processes_async (mount_source, + message, + processes, + choices, + g_strv_length ((gchar **) choices), + op_show_processes_reply, + g_object_ref (op)); + g_signal_stop_emission_by_name (op, "show_processes"); + return TRUE; +} + +gboolean +g_mount_source_abort (GMountSource *source) { DBusMessage *message; DBusConnection *connection; + gboolean ret; + + ret = FALSE; /* If no dbus id specified, reply that we weren't handled */ if (source->dbus_id[0] == 0) @@ -713,7 +942,7 @@ op_aborted (GMountOperation *op, connection = dbus_bus_get (DBUS_BUS_SESSION, NULL); if (connection == NULL) goto out; - + message = dbus_message_new_method_call (source->dbus_id, source->obj_path, G_VFS_DBUS_MOUNT_OPERATION_INTERFACE, @@ -725,8 +954,24 @@ op_aborted (GMountOperation *op, dbus_message_unref (message); } + ret = TRUE; + out: - return TRUE; + return ret; +} + +static void +op_aborted (GMountOperation *op, + GMountSource *source) +{ + g_mount_source_abort (source); +} + +gboolean +g_mount_source_is_dummy (GMountSource *source) +{ + g_return_val_if_fail (G_IS_MOUNT_SOURCE (source), TRUE); + return source->dbus_id[0] == 0; } @@ -742,6 +987,7 @@ g_mount_source_get_operation (GMountSource *mount_source) g_signal_connect (op, "ask_password", (GCallback)op_ask_password, mount_source); g_signal_connect (op, "ask_question", (GCallback)op_ask_question, mount_source); + g_signal_connect (op, "show_processes", (GCallback)op_show_processes, mount_source); g_signal_connect (op, "aborted", (GCallback)op_aborted, mount_source); return op; diff --git a/common/gmountsource.h b/common/gmountsource.h index e4298357..1f973a10 100644 --- a/common/gmountsource.h +++ b/common/gmountsource.h @@ -104,6 +104,31 @@ gboolean g_mount_source_ask_question_finish (GMountSource gboolean *aborted, gint *choice_out); +gboolean g_mount_source_show_processes (GMountSource *mount_source, + const char *message, + GArray *processes, + const char **choices, + gint n_choices, + gboolean *aborted, + gint *choice_out); + +void g_mount_source_show_processes_async (GMountSource *mount_source, + const char *message, + GArray *processes, + const char **choices, + gint n_choices, + GAsyncReadyCallback callback, + gpointer user_data); + +gboolean g_mount_source_show_processes_finish (GMountSource *source, + GAsyncResult *result, + gboolean *aborted, + gint *choice_out); + +gboolean g_mount_source_abort (GMountSource *source); + +gboolean g_mount_source_is_dummy (GMountSource *source); + const char * g_mount_source_get_dbus_id (GMountSource *mount_source); const char * g_mount_source_get_obj_path (GMountSource *mount_source); diff --git a/common/gvfsdaemonprotocol.h b/common/gvfsdaemonprotocol.h index 77658549..98779f72 100644 --- a/common/gvfsdaemonprotocol.h +++ b/common/gvfsdaemonprotocol.h @@ -39,6 +39,7 @@ G_BEGIN_DECLS #define G_VFS_DBUS_MOUNT_OP_EJECT_MOUNTABLE "EjectMountable" #define G_VFS_DBUS_MOUNT_OP_START_MOUNTABLE "StartMountable" #define G_VFS_DBUS_MOUNT_OP_STOP_MOUNTABLE "StopMountable" +#define G_VFS_DBUS_MOUNT_OP_POLL_MOUNTABLE "PollMountable" #define G_VFS_DBUS_MOUNT_OP_SET_DISPLAY_NAME "SetDisplayName" #define G_VFS_DBUS_MOUNT_OP_DELETE "Delete" #define G_VFS_DBUS_MOUNT_OP_TRASH "Trash" @@ -75,6 +76,7 @@ G_BEGIN_DECLS #define G_VFS_DBUS_MOUNT_OPERATION_INTERFACE "org.gtk.vfs.MountOperation" #define G_VFS_DBUS_MOUNT_OPERATION_OP_ASK_PASSWORD "askPassword" #define G_VFS_DBUS_MOUNT_OPERATION_OP_ASK_QUESTION "askQuestion" +#define G_VFS_DBUS_MOUNT_OPERATION_OP_SHOW_PROCESSES "showProcesses" #define G_VFS_DBUS_MOUNT_OPERATION_OP_ABORTED "aborted" /* Implemented by the spawner of a process, the spawned process sends the |