diff options
author | Cosimo Cecchi <cosimoc@gnome.org> | 2012-06-20 21:36:09 -0400 |
---|---|---|
committer | Cosimo Cecchi <cosimoc@gnome.org> | 2012-06-22 16:49:05 -0400 |
commit | 44fd03eb47b9492ffaf32ae6dfcca00b7d5a7618 (patch) | |
tree | 2e8925910f97f09d2ac29a5e9cd501392ba1fdf0 /gtk/gtkmountoperation.c | |
parent | fb91fa2fbd5ca93afd44744d23c47518cef55ef4 (diff) | |
download | gtk+-44fd03eb47b9492ffaf32ae6dfcca00b7d5a7618.tar.gz |
mountoperation: use the Shell DBus proxy if available
Make GMountOperation look for an owner of org.Gtk.MountOperationHandler
if possible, and use it instead of the GTK-based dialogs.
This allows applications to use the implementation offered by the
desktop shell, if available, through a DBus private interface:
org.Gtk.MountOperationHandler.
https://bugzilla.gnome.org/show_bug.cgi?id=674963
Diffstat (limited to 'gtk/gtkmountoperation.c')
-rw-r--r-- | gtk/gtkmountoperation.c | 343 |
1 files changed, 312 insertions, 31 deletions
diff --git a/gtk/gtkmountoperation.c b/gtk/gtkmountoperation.c index 4f070a73cd..38aadcaef0 100644 --- a/gtk/gtkmountoperation.c +++ b/gtk/gtkmountoperation.c @@ -29,6 +29,7 @@ #include "gtkmountoperationprivate.h" #include "gtkbox.h" +#include "gtkdbusgenerated.h" #include "gtkentry.h" #include "gtkbox.h" #include "gtkintl.h" @@ -49,6 +50,8 @@ #include "gtkimagemenuitem.h" #include "gtkmain.h" +#include <glib/gprintf.h> + /** * SECTION:filesystem * @short_description: Functions for working with GIO @@ -115,6 +118,11 @@ struct _GtkMountOperationPrivate { GtkDialog *dialog; GdkScreen *screen; + /* bus proxy */ + GtkMountOperationHandler *handler; + GCancellable *cancellable; + gboolean handler_showing; + /* for the ask-password dialog */ GtkWidget *entry_container; GtkWidget *username_entry; @@ -176,9 +184,22 @@ gtk_mount_operation_class_init (GtkMountOperationClass *klass) static void gtk_mount_operation_init (GtkMountOperation *operation) { + gchar *name_owner; + operation->priv = G_TYPE_INSTANCE_GET_PRIVATE (operation, GTK_TYPE_MOUNT_OPERATION, GtkMountOperationPrivate); + + operation->priv->handler = + gtk_mount_operation_handler_proxy_new_for_bus_sync (G_BUS_TYPE_SESSION, + G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START, + "org.gtk.MountOperationHandler", + "/org/gtk/MountOperationHandler", + NULL, NULL); + name_owner = g_dbus_proxy_get_name_owner (G_DBUS_PROXY (operation->priv->handler)); + if (!name_owner) + g_clear_object (&operation->priv->handler); + g_free (name_owner); } static void @@ -193,6 +214,9 @@ gtk_mount_operation_finalize (GObject *object) if (priv->screen) g_object_unref (priv->screen); + if (priv->handler) + g_object_unref (priv->handler); + G_OBJECT_CLASS (gtk_mount_operation_parent_class)->finalize (object); } @@ -237,7 +261,7 @@ gtk_mount_operation_get_property (GObject *object, break; case PROP_IS_SHOWING: - g_value_set_boolean (value, priv->dialog != NULL); + g_value_set_boolean (value, priv->dialog != NULL || priv->handler_showing); break; case PROP_SCREEN: @@ -251,6 +275,21 @@ gtk_mount_operation_get_property (GObject *object, } static void +gtk_mount_operation_proxy_finish (GtkMountOperation *op, + GMountOperationResult result) +{ + gtk_mount_operation_handler_call_close (op->priv->handler, NULL, NULL, NULL); + + op->priv->handler_showing = FALSE; + g_object_notify (G_OBJECT (op), "is-showing"); + + g_mount_operation_reply (G_MOUNT_OPERATION (op), result); + + /* drop the reference acquired when calling the proxy method */ + g_object_unref (op); +} + +static void remember_button_toggled (GtkToggleButton *button, GtkMountOperation *operation) { @@ -436,13 +475,11 @@ table_add_entry (GtkWidget *table, } static void -gtk_mount_operation_ask_password (GMountOperation *mount_op, - const char *message, - const char *default_user, - const char *default_domain, - GAskPasswordFlags flags) +gtk_mount_operation_ask_password_do_gtk (GtkMountOperation *operation, + const gchar *message, + const gchar *default_user, + const gchar *default_domain) { - GtkMountOperation *operation; GtkMountOperationPrivate *priv; GtkWidget *widget; GtkDialog *dialog; @@ -455,11 +492,8 @@ gtk_mount_operation_ask_password (GMountOperation *mount_op, guint rows; const gchar *secondary; - operation = GTK_MOUNT_OPERATION (mount_op); priv = operation->priv; - priv->ask_flags = flags; - widget = gtk_dialog_new (); dialog = GTK_DIALOG (widget); window = GTK_WINDOW (widget); @@ -538,7 +572,7 @@ gtk_mount_operation_ask_password (GMountOperation *mount_op, vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 6); gtk_box_pack_start (GTK_BOX (main_vbox), vbox, FALSE, FALSE, 0); - can_anonymous = flags & G_ASK_PASSWORD_ANONYMOUS_SUPPORTED; + can_anonymous = priv->ask_flags & G_ASK_PASSWORD_ANONYMOUS_SUPPORTED; priv->anonymous_toggle = NULL; if (can_anonymous) @@ -570,13 +604,13 @@ gtk_mount_operation_ask_password (GMountOperation *mount_op, rows = 0; - if (flags & G_ASK_PASSWORD_NEED_PASSWORD) + if (priv->ask_flags & G_ASK_PASSWORD_NEED_PASSWORD) rows++; - if (flags & G_ASK_PASSWORD_NEED_USERNAME) + if (priv->ask_flags & G_ASK_PASSWORD_NEED_USERNAME) rows++; - if (flags &G_ASK_PASSWORD_NEED_DOMAIN) + if (priv->ask_flags &G_ASK_PASSWORD_NEED_DOMAIN) rows++; /* The table that holds the entries */ @@ -593,24 +627,25 @@ gtk_mount_operation_ask_password (GMountOperation *mount_op, rows = 0; priv->username_entry = NULL; - if (flags & G_ASK_PASSWORD_NEED_USERNAME) + + if (priv->ask_flags & G_ASK_PASSWORD_NEED_USERNAME) priv->username_entry = table_add_entry (table, rows++, _("_Username:"), default_user, operation); priv->domain_entry = NULL; - if (flags & G_ASK_PASSWORD_NEED_DOMAIN) + if (priv->ask_flags & G_ASK_PASSWORD_NEED_DOMAIN) priv->domain_entry = table_add_entry (table, rows++, _("_Domain:"), default_domain, operation); priv->password_entry = NULL; - if (flags & G_ASK_PASSWORD_NEED_PASSWORD) + if (priv->ask_flags & G_ASK_PASSWORD_NEED_PASSWORD) { priv->password_entry = table_add_entry (table, rows++, _("_Password:"), NULL, operation); gtk_entry_set_visibility (GTK_ENTRY (priv->password_entry), FALSE); } - if (flags & G_ASK_PASSWORD_SAVING_SUPPORTED) + if (priv->ask_flags & G_ASK_PASSWORD_SAVING_SUPPORTED) { GtkWidget *choice; GtkWidget *remember_box; @@ -621,7 +656,7 @@ gtk_mount_operation_ask_password (GMountOperation *mount_op, gtk_box_pack_start (GTK_BOX (vbox), remember_box, FALSE, FALSE, 0); - password_save = g_mount_operation_get_password_save (mount_op); + password_save = g_mount_operation_get_password_save (G_MOUNT_OPERATION (operation)); choice = gtk_radio_button_new_with_mnemonic (NULL, _("Forget password _immediately")); gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (choice), @@ -682,6 +717,89 @@ gtk_mount_operation_ask_password (GMountOperation *mount_op, } static void +call_password_proxy_cb (GObject *source, + GAsyncResult *res, + gpointer user_data) +{ + GtkMountOperationHandler *proxy = GTK_MOUNT_OPERATION_HANDLER (source); + GMountOperation *op = user_data; + GMountOperationResult result; + GVariant *result_details; + GVariantIter iter; + const gchar *key; + GVariant *value; + GError *error = NULL; + + if (!gtk_mount_operation_handler_call_ask_password_finish (proxy, + &result, &result_details, res, &error)) + { + result = G_MOUNT_OPERATION_ABORTED; + g_warning ("Shell mount operation error: %s\n", error->message); + g_error_free (error); + goto out; + } + + g_variant_iter_init (&iter, result_details); + while (g_variant_iter_loop (&iter, "{&sv}", &key, &value)) + { + if (strcmp (key, "password") == 0) + g_mount_operation_set_password (op, g_variant_get_string (value, NULL)); + else if (strcmp (key, "password_save") == 0) + g_mount_operation_set_password_save (op, g_variant_get_uint32 (value)); + } + + out: + gtk_mount_operation_proxy_finish (GTK_MOUNT_OPERATION (op), result); +} + +static void +gtk_mount_operation_ask_password_do_proxy (GtkMountOperation *operation, + const char *message, + const char *default_user, + const char *default_domain) +{ + gchar id[255]; + g_sprintf(id, "GtkMountOperation%p", operation); + + operation->priv->handler_showing = TRUE; + g_object_notify (G_OBJECT (operation), "is-showing"); + + /* keep a ref to the operation while the handler is showing */ + g_object_ref (operation); + + gtk_mount_operation_handler_call_ask_password (operation->priv->handler, id, + message, "drive-harddisk", + default_user, default_domain, + operation->priv->ask_flags, NULL, + call_password_proxy_cb, operation); +} + +static void +gtk_mount_operation_ask_password (GMountOperation *mount_op, + const char *message, + const char *default_user, + const char *default_domain, + GAskPasswordFlags flags) +{ + GtkMountOperation *operation; + GtkMountOperationPrivate *priv; + gboolean use_gtk; + + operation = GTK_MOUNT_OPERATION (mount_op); + priv = operation->priv; + priv->ask_flags = flags; + + use_gtk = (operation->priv->handler == NULL) || + (priv->ask_flags & G_ASK_PASSWORD_NEED_DOMAIN) || + (priv->ask_flags & G_ASK_PASSWORD_NEED_USERNAME); + + if (use_gtk) + gtk_mount_operation_ask_password_do_gtk (operation, message, default_user, default_domain); + else + gtk_mount_operation_ask_password_do_proxy (operation, message, default_user, default_domain); +} + +static void question_dialog_button_clicked (GtkDialog *dialog, gint button_number, GMountOperation *op) @@ -707,9 +825,9 @@ question_dialog_button_clicked (GtkDialog *dialog, } static void -gtk_mount_operation_ask_question (GMountOperation *op, - const char *message, - const char *choices[]) +gtk_mount_operation_ask_question_do_gtk (GtkMountOperation *op, + const char *message, + const char *choices[]) { GtkMountOperationPrivate *priv; GtkWidget *dialog; @@ -721,7 +839,7 @@ gtk_mount_operation_ask_question (GMountOperation *op, g_return_if_fail (message != NULL); g_return_if_fail (choices != NULL); - priv = GTK_MOUNT_OPERATION (op)->priv; + priv = op->priv; primary = strstr (message, "\n"); if (primary) @@ -763,6 +881,77 @@ gtk_mount_operation_ask_question (GMountOperation *op, } static void +call_question_proxy_cb (GObject *source, + GAsyncResult *res, + gpointer user_data) +{ + GtkMountOperationHandler *proxy = GTK_MOUNT_OPERATION_HANDLER (source); + GMountOperation *op = user_data; + GMountOperationResult result; + GVariant *result_details; + GVariantIter iter; + const gchar *key; + GVariant *value; + GError *error = NULL; + + if (!gtk_mount_operation_handler_call_ask_question_finish (proxy, &result, + &result_details, res, &error)) + { + result = G_MOUNT_OPERATION_ABORTED; + g_warning ("Shell mount operation error: %s\n", error->message); + g_error_free (error); + goto out; + } + + g_variant_iter_init (&iter, result_details); + while (g_variant_iter_loop (&iter, "{&sv}", &key, &value)) + { + if (strcmp (key, "choice") == 0) + g_mount_operation_set_choice (op, g_variant_get_int32 (value)); + } + + out: + gtk_mount_operation_proxy_finish (GTK_MOUNT_OPERATION (op), result); +} + +static void +gtk_mount_operation_ask_question_do_proxy (GtkMountOperation *operation, + const char *message, + const char *choices[]) +{ + gchar id[255]; + g_sprintf(id, "GtkMountOperation%p", operation); + + operation->priv->handler_showing = TRUE; + g_object_notify (G_OBJECT (operation), "is-showing"); + + /* keep a ref to the operation while the handler is showing */ + g_object_ref (operation); + + gtk_mount_operation_handler_call_ask_question (operation->priv->handler, id, + message, "drive-harddisk", + choices, NULL, + call_question_proxy_cb, operation); +} + +static void +gtk_mount_operation_ask_question (GMountOperation *op, + const char *message, + const char *choices[]) +{ + GtkMountOperation *operation; + gboolean use_gtk; + + operation = GTK_MOUNT_OPERATION (op); + use_gtk = (operation->priv->handler == NULL); + + if (use_gtk) + gtk_mount_operation_ask_question_do_gtk (operation, message, choices); + else + gtk_mount_operation_ask_question_do_proxy (operation, message, choices); +} + +static void show_processes_button_clicked (GtkDialog *dialog, gint button_number, GMountOperation *op) @@ -1174,7 +1363,7 @@ on_button_press_event_for_process_tree_view (GtkWidget *widget, } static GtkWidget * -create_show_processes_dialog (GMountOperation *op, +create_show_processes_dialog (GtkMountOperation *op, const char *message, const char *choices[]) { @@ -1193,7 +1382,7 @@ create_show_processes_dialog (GMountOperation *op, GtkListStore *list_store; gchar *s; - priv = GTK_MOUNT_OPERATION (op)->priv; + priv = op->priv; primary = strstr (message, "\n"); if (primary) @@ -1306,10 +1495,74 @@ create_show_processes_dialog (GMountOperation *op, } static void -gtk_mount_operation_show_processes (GMountOperation *op, - const char *message, - GArray *processes, - const char *choices[]) +call_processes_proxy_cb (GObject *source, + GAsyncResult *res, + gpointer user_data) +{ + GtkMountOperationHandler *proxy = GTK_MOUNT_OPERATION_HANDLER (source); + GMountOperation *op = user_data; + GMountOperationResult result; + GVariant *result_details; + GVariantIter iter; + const gchar *key; + GVariant *value; + GError *error = NULL; + + if (!gtk_mount_operation_handler_call_show_processes_finish (proxy, + &result, &result_details, res, &error)) + { + result = G_MOUNT_OPERATION_ABORTED; + g_warning ("Shell mount operation error: %s\n", error->message); + g_error_free (error); + goto out; + } + + /* If the request was unhandled it means we called the method again; + * in this case, just return and wait for the next response. + */ + if (result == G_MOUNT_OPERATION_UNHANDLED) + return; + + g_variant_iter_init (&iter, result_details); + while (g_variant_iter_loop (&iter, "{&sv}", &key, &value)) + { + if (strcmp (key, "choice") == 0) + g_mount_operation_set_choice (op, g_variant_get_int32 (value)); + } + + out: + gtk_mount_operation_proxy_finish (GTK_MOUNT_OPERATION (op), result); +} + +static void +gtk_mount_operation_show_processes_do_proxy (GtkMountOperation *operation, + const char *message, + GArray *processes, + const char *choices[]) +{ + gchar id[255]; + g_sprintf(id, "GtkMountOperation%p", operation); + + operation->priv->handler_showing = TRUE; + g_object_notify (G_OBJECT (operation), "is-showing"); + + /* keep a ref to the operation while the handler is showing */ + g_object_ref (operation); + + gtk_mount_operation_handler_call_show_processes (operation->priv->handler, id, + message, "drive-harddisk", + g_variant_new_fixed_array (G_VARIANT_TYPE_INT32, + processes->data, processes->len, + sizeof (GPid)), + choices, NULL, + call_processes_proxy_cb, operation); +} + +static void +gtk_mount_operation_show_processes_do_gtk (GtkMountOperation *op, + const char *message, + GArray *processes, + const char *choices[]) { GtkMountOperationPrivate *priv; GtkWidget *dialog = NULL; @@ -1319,7 +1572,7 @@ gtk_mount_operation_show_processes (GMountOperation *op, g_return_if_fail (processes != NULL); g_return_if_fail (choices != NULL); - priv = GTK_MOUNT_OPERATION (op)->priv; + priv = op->priv; if (priv->process_list_store == NULL) { @@ -1329,7 +1582,7 @@ gtk_mount_operation_show_processes (GMountOperation *op, /* otherwise, we're showing the dialog, assume messages+choices hasn't changed */ - update_process_list_store (GTK_MOUNT_OPERATION (op), + update_process_list_store (op, priv->process_list_store, processes); @@ -1339,6 +1592,26 @@ gtk_mount_operation_show_processes (GMountOperation *op, } } + +static void +gtk_mount_operation_show_processes (GMountOperation *op, + const char *message, + GArray *processes, + const char *choices[]) +{ + + GtkMountOperation *operation; + gboolean use_gtk; + + operation = GTK_MOUNT_OPERATION (op); + use_gtk = (operation->priv->handler == NULL); + + if (use_gtk) + gtk_mount_operation_show_processes_do_gtk (operation, message, processes, choices); + else + gtk_mount_operation_show_processes_do_proxy (operation, message, processes, choices); +} + static void gtk_mount_operation_aborted (GMountOperation *op) { @@ -1353,6 +1626,14 @@ gtk_mount_operation_aborted (GMountOperation *op) g_object_notify (G_OBJECT (op), "is-showing"); g_object_unref (op); } + + if (priv->handler != NULL) + { + gtk_mount_operation_handler_call_close (priv->handler, NULL, NULL, NULL); + + priv->handler_showing = FALSE; + g_object_notify (G_OBJECT (op), "is-showing"); + } } /** |