gboolean gtk_file_chooser_native_portal_show (GtkFileChooserNative *self) { FilechooserPortalData *data; GtkWindow *transient_for; GDBusConnection *connection; char *parent_window_str; GDBusMessage *message; GVariantBuilder opt_builder; GtkFileChooserAction action; gboolean multiple; const char *method_name; if (!gtk_should_use_portal ()) return FALSE; connection = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, NULL); if (connection == NULL) return FALSE; action = gtk_file_chooser_get_action (GTK_FILE_CHOOSER (self)); multiple = gtk_file_chooser_get_select_multiple (GTK_FILE_CHOOSER (self)); if (action == GTK_FILE_CHOOSER_ACTION_OPEN) method_name = "OpenFile"; else if (action == GTK_FILE_CHOOSER_ACTION_SAVE) method_name = "SaveFile"; else { g_warning ("GTK_FILE_CHOOSER_ACTION_%s is not supported by GtkFileChooserNativePortal", action == GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER ? "SELECT_FOLDER" : "CREATE_FOLDER"); return FALSE; } data = g_new0 (FilechooserPortalData, 1); data->self = g_object_ref (self); data->connection = connection; message = g_dbus_message_new_method_call ("org.freedesktop.portal.Desktop", "/org/freedesktop/portal/desktop", "org.freedesktop.portal.FileChooser", method_name); parent_window_str = NULL; transient_for = gtk_native_dialog_get_transient_for (GTK_NATIVE_DIALOG (self)); if (transient_for != NULL && gtk_widget_is_visible (GTK_WIDGET (transient_for))) { GdkWindow *window = gtk_widget_get_window (GTK_WIDGET (transient_for)); #ifdef GDK_WINDOWING_X11 if (GDK_IS_X11_WINDOW(window)) parent_window_str = g_strdup_printf ("x11:%x", (guint32)gdk_x11_window_get_xid (window)); #endif } if (gtk_native_dialog_get_modal (GTK_NATIVE_DIALOG (self))) data->modal = TRUE; if (data->modal && transient_for != NULL) { data->grab_widget = gtk_invisible_new_for_screen (gtk_widget_get_screen (GTK_WIDGET (transient_for))); gtk_grab_add (GTK_WIDGET (data->grab_widget)); } g_variant_builder_init (&opt_builder, G_VARIANT_TYPE_VARDICT); g_variant_builder_add (&opt_builder, "{sv}", "multiple", g_variant_new_boolean (multiple)); if (self->accept_label) g_variant_builder_add (&opt_builder, "{sv}", "accept_label", g_variant_new_string (self->accept_label)); if (self->cancel_label) g_variant_builder_add (&opt_builder, "{sv}", "cancel_label", g_variant_new_string (self->cancel_label)); g_variant_builder_add (&opt_builder, "{sv}", "modal", g_variant_new_boolean (data->modal)); g_variant_builder_add (&opt_builder, "{sv}", "filters", get_filters (GTK_FILE_CHOOSER (self))); if (GTK_FILE_CHOOSER_NATIVE (self)->current_name) g_variant_builder_add (&opt_builder, "{sv}", "current_name", g_variant_new_string (GTK_FILE_CHOOSER_NATIVE (self)->current_name)); if (GTK_FILE_CHOOSER_NATIVE (self)->current_folder) { gchar *path; path = g_file_get_path (GTK_FILE_CHOOSER_NATIVE (self)->current_folder); g_variant_builder_add (&opt_builder, "{sv}", "current_folder", g_variant_new_bytestring (path)); g_free (path); } if (GTK_FILE_CHOOSER_NATIVE (self)->current_file) { gchar *path; path = g_file_get_path (GTK_FILE_CHOOSER_NATIVE (self)->current_file); g_variant_builder_add (&opt_builder, "{sv}", "current_file", g_variant_new_bytestring (path)); g_free (path); } if (GTK_FILE_CHOOSER_NATIVE (self)->choices) g_variant_builder_add (&opt_builder, "{sv}", "choices", serialize_choices (GTK_FILE_CHOOSER_NATIVE (self))); g_dbus_message_set_body (message, g_variant_new ("(ss@a{sv})", parent_window_str ? parent_window_str : "", gtk_native_dialog_get_title (GTK_NATIVE_DIALOG (self)), g_variant_builder_end (&opt_builder))); g_free (parent_window_str); g_dbus_connection_send_message_with_reply (data->connection, message, G_DBUS_SEND_MESSAGE_FLAGS_NONE, G_MAXINT, NULL, NULL, open_file_msg_cb, data); g_object_unref (message); self->mode_data = data; return TRUE; }
/** * fu_util_install_internal: **/ static gboolean fu_util_install_internal (FuUtilPrivate *priv, const gchar *id, const gchar *filename, GError **error) { GVariant *body; GVariantBuilder builder; gint retval; gint fd; _cleanup_object_unref_ GDBusMessage *request = NULL; _cleanup_object_unref_ GUnixFDList *fd_list = NULL; /* set options */ g_variant_builder_init (&builder, G_VARIANT_TYPE_ARRAY); g_variant_builder_add (&builder, "{sv}", "reason", g_variant_new_string ("user-action")); g_variant_builder_add (&builder, "{sv}", "filename", g_variant_new_string (filename)); if (priv->flags & FU_PROVIDER_UPDATE_FLAG_OFFLINE) { g_variant_builder_add (&builder, "{sv}", "offline", g_variant_new_boolean (TRUE)); } if (priv->flags & FU_PROVIDER_UPDATE_FLAG_ALLOW_OLDER) { g_variant_builder_add (&builder, "{sv}", "allow-older", g_variant_new_boolean (TRUE)); } if (priv->flags & FU_PROVIDER_UPDATE_FLAG_ALLOW_REINSTALL) { g_variant_builder_add (&builder, "{sv}", "allow-reinstall", g_variant_new_boolean (TRUE)); } /* open file */ fd = open (filename, O_RDONLY); if (fd < 0) { g_set_error (error, FWUPD_ERROR, FWUPD_ERROR_INVALID_FILE, "failed to open %s", filename); return FALSE; } /* set out of band file descriptor */ fd_list = g_unix_fd_list_new (); retval = g_unix_fd_list_append (fd_list, fd, NULL); g_assert (retval != -1); request = g_dbus_message_new_method_call (FWUPD_DBUS_SERVICE, FWUPD_DBUS_PATH, FWUPD_DBUS_INTERFACE, "Install"); g_dbus_message_set_unix_fd_list (request, fd_list); /* g_unix_fd_list_append did a dup() already */ close (fd); /* send message */ body = g_variant_new ("(sha{sv})", id, fd > -1 ? 0 : -1, &builder); g_dbus_message_set_body (request, body); g_dbus_connection_send_message_with_reply (priv->conn, request, G_DBUS_SEND_MESSAGE_FLAGS_NONE, -1, NULL, NULL, fu_util_update_cb, priv); g_main_loop_run (priv->loop); if (priv->message == NULL) { g_dbus_error_strip_remote_error (priv->error); g_propagate_error (error, priv->error); return FALSE; } if (g_dbus_message_to_gerror (priv->message, error)) { g_dbus_error_strip_remote_error (*error); return FALSE; } /* TRANSLATORS: update completed, no errors */ g_print ("%s\n", _("Done!")); return TRUE; }
/** * fu_util_refresh_internal: **/ static gboolean fu_util_refresh_internal (FuUtilPrivate *priv, const gchar *data_fn, const gchar *sig_fn, GError **error) { GVariant *body; gint fd; gint fd_sig; _cleanup_object_unref_ GDBusMessage *request = NULL; _cleanup_object_unref_ GUnixFDList *fd_list = NULL; /* open file */ fd = open (data_fn, O_RDONLY); if (fd < 0) { g_set_error (error, FWUPD_ERROR, FWUPD_ERROR_INVALID_FILE, "failed to open %s", data_fn); return FALSE; } fd_sig = open (sig_fn, O_RDONLY); if (fd_sig < 0) { g_set_error (error, FWUPD_ERROR, FWUPD_ERROR_INVALID_FILE, "failed to open %s", sig_fn); return FALSE; } /* set out of band file descriptor */ fd_list = g_unix_fd_list_new (); g_unix_fd_list_append (fd_list, fd, NULL); g_unix_fd_list_append (fd_list, fd_sig, NULL); request = g_dbus_message_new_method_call (FWUPD_DBUS_SERVICE, FWUPD_DBUS_PATH, FWUPD_DBUS_INTERFACE, "UpdateMetadata"); g_dbus_message_set_unix_fd_list (request, fd_list); /* g_unix_fd_list_append did a dup() already */ close (fd); close (fd_sig); /* send message */ body = g_variant_new ("(hh)", fd, fd_sig); g_dbus_message_set_body (request, body); g_dbus_connection_send_message_with_reply (priv->conn, request, G_DBUS_SEND_MESSAGE_FLAGS_NONE, -1, NULL, NULL, fu_util_update_cb, priv); g_main_loop_run (priv->loop); if (priv->message == NULL) { g_dbus_error_strip_remote_error (priv->error); g_propagate_error (error, priv->error); return FALSE; } if (g_dbus_message_to_gerror (priv->message, error)) { g_dbus_error_strip_remote_error (*error); return FALSE; } return TRUE; }
gboolean eas_gdbus_call (struct eas_gdbus_client *client, const gchar *object, const gchar *interface, const gchar *method, EasProgressFn progress_fn, gpointer progress_data, const gchar *in_params, const gchar *out_params, GCancellable *cancellable, GError **error, ...) { GDBusMessage *message; struct _eas_call_data call; GMainContext *ctxt; GVariant *v = NULL; va_list ap; gboolean success; guint cancel_handler_id; guint32 serial = 0; va_start (ap, error); message = g_dbus_message_new_method_call (EAS_SERVICE_NAME, object, interface, method); v = g_variant_new_va (in_params, NULL, &ap); g_dbus_message_set_body (message, v); call.cancelled = FALSE; call.result = NULL; ctxt = g_main_context_new (); call.loop = g_main_loop_new (ctxt, FALSE); g_main_context_push_thread_default (ctxt); g_dbus_connection_send_message_with_reply (client->connection, message, G_DBUS_SEND_MESSAGE_FLAGS_NONE, 1000000, &serial, cancellable, _call_done, (gpointer) &call); g_object_unref (message); if (cancellable) cancel_handler_id = g_cancellable_connect (cancellable, G_CALLBACK (_call_cancel), (gpointer) &call, NULL); /* Ignore error; it's not the end of the world if progress info is lost, and it should never happen anyway */ if (progress_fn) eas_client_add_progress_info_to_table (client, serial, progress_fn, progress_data, NULL); g_main_loop_run (call.loop); if (cancellable) g_cancellable_disconnect (cancellable, cancel_handler_id); success = eas_gdbus_call_finish (client, call.result, call.cancelled ? serial : 0, out_params, &ap, error); if (serial && progress_fn) { EasProgressCallbackInfo *cbinfo; g_mutex_lock (client->progress_lock); cbinfo = g_hash_table_lookup (client->progress_fns_table, GUINT_TO_POINTER (serial)); if (cbinfo && cbinfo->calling) { g_debug ("Progress for call %u is running; wait for it to complete", serial); g_hash_table_steal (client->progress_fns_table, GUINT_TO_POINTER (serial)); do { g_cond_wait (client->progress_cond, client->progress_lock); } while (cbinfo->calling); g_free (cbinfo); } else if (cbinfo) { g_hash_table_remove (client->progress_fns_table, GUINT_TO_POINTER (serial)); } g_mutex_unlock (client->progress_lock); } va_end (ap); g_main_context_pop_thread_default (ctxt); g_main_context_unref (ctxt); g_main_loop_unref (call.loop); g_object_unref (call.result); return success; }