|
Packit |
b00eeb |
/*
|
|
Packit |
b00eeb |
* gnome-keyring
|
|
Packit |
b00eeb |
*
|
|
Packit |
b00eeb |
* Copyright (C) 2011 Stefan Walter
|
|
Packit |
b00eeb |
*
|
|
Packit |
b00eeb |
* This program is free software; you can redistribute it and/or modify
|
|
Packit |
b00eeb |
* it under the terms of the GNU Lesser General Public License as
|
|
Packit |
b00eeb |
* published by the Free Software Foundation; either version 2.1 of
|
|
Packit |
b00eeb |
* the License, or (at your option) any later version.
|
|
Packit |
b00eeb |
*
|
|
Packit |
b00eeb |
* This program is distributed in the hope that it will be useful, but
|
|
Packit |
b00eeb |
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
Packit |
b00eeb |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
Packit |
b00eeb |
* Lesser General Public License for more details.
|
|
Packit |
b00eeb |
*
|
|
Packit |
b00eeb |
* You should have received a copy of the GNU Lesser General Public
|
|
Packit |
b00eeb |
* License along with this program; if not, see <http://www.gnu.org/licenses/>.
|
|
Packit |
b00eeb |
*
|
|
Packit |
b00eeb |
* Author: Stef Walter <stef@thewalter.net>
|
|
Packit |
b00eeb |
*/
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
#include "config.h"
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
#include "gcr-dbus-constants.h"
|
|
Packit |
b00eeb |
#include "gcr-internal.h"
|
|
Packit |
b00eeb |
#include "gcr-library.h"
|
|
Packit |
b00eeb |
#include "gcr-prompt.h"
|
|
Packit |
b00eeb |
#include "gcr-secret-exchange.h"
|
|
Packit |
b00eeb |
#include "gcr-system-prompt.h"
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
#include "gcr/gcr-dbus-generated.h"
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
#include "egg/egg-error.h"
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
#include <glib/gi18n.h>
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
/**
|
|
Packit |
b00eeb |
* SECTION:gcr-system-prompt
|
|
Packit |
b00eeb |
* @title: GcrSystemPrompt
|
|
Packit |
b00eeb |
* @short_description: a system modal prompt
|
|
Packit |
b00eeb |
*
|
|
Packit |
b00eeb |
* A #GcrPrompt implementation which calls to the system prompter to
|
|
Packit |
b00eeb |
* display prompts in a system modal fashion.
|
|
Packit |
b00eeb |
*
|
|
Packit |
b00eeb |
* Since the system prompter usually only displays one prompt at a time, you
|
|
Packit |
b00eeb |
* may have to wait for the prompt to be displayed. Use gcr_system_prompt_open()
|
|
Packit |
b00eeb |
* or a related function to open a prompt. Since this can take a long time, you
|
|
Packit |
b00eeb |
* should always check that the prompt is still needed after it is opened. A
|
|
Packit |
b00eeb |
* previous prompt may have already provided the information needed and you
|
|
Packit |
b00eeb |
* may no longer need to prompt.
|
|
Packit |
b00eeb |
*
|
|
Packit |
b00eeb |
* Use gcr_system_prompt_close() to close the prompt when you're done with it.
|
|
Packit |
b00eeb |
*/
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
/**
|
|
Packit |
b00eeb |
* GcrSystemPrompt:
|
|
Packit |
b00eeb |
*
|
|
Packit |
b00eeb |
* A #GcrPrompt which shows a system prompt. This is usually a system modal
|
|
Packit |
b00eeb |
* dialog.
|
|
Packit |
b00eeb |
*/
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
/**
|
|
Packit |
b00eeb |
* GcrSystemPromptClass:
|
|
Packit |
b00eeb |
* @parent_class: parent class
|
|
Packit |
b00eeb |
*
|
|
Packit |
b00eeb |
* The class for #GcrSystemPrompt.
|
|
Packit |
b00eeb |
*/
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
/**
|
|
Packit |
b00eeb |
* GCR_SYSTEM_PROMPT_ERROR:
|
|
Packit |
b00eeb |
*
|
|
Packit |
b00eeb |
* The domain for errors returned from GcrSystemPrompt methods.
|
|
Packit |
b00eeb |
*/
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
/**
|
|
Packit |
b00eeb |
* GcrSystemPromptError:
|
|
Packit |
b00eeb |
* @GCR_SYSTEM_PROMPT_IN_PROGRESS: another prompt is already in progress
|
|
Packit |
b00eeb |
*
|
|
Packit |
b00eeb |
* No error returned by the #GcrSystemPrompt is suitable for display or
|
|
Packit |
b00eeb |
* to the user.
|
|
Packit |
b00eeb |
*
|
|
Packit |
b00eeb |
* If the system prompter can only show one prompt at a time, and there is
|
|
Packit |
b00eeb |
* already a prompt being displayed, and the timeout waiting to open the
|
|
Packit |
b00eeb |
* prompt expires, then %GCR_SYSTEM_PROMPT_IN_PROGRESS is returned.
|
|
Packit |
b00eeb |
*/
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
enum {
|
|
Packit |
b00eeb |
PROP_0,
|
|
Packit |
b00eeb |
PROP_BUS_NAME,
|
|
Packit |
b00eeb |
PROP_SECRET_EXCHANGE,
|
|
Packit |
b00eeb |
PROP_TIMEOUT_SECONDS,
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
PROP_TITLE,
|
|
Packit |
b00eeb |
PROP_MESSAGE,
|
|
Packit |
b00eeb |
PROP_DESCRIPTION,
|
|
Packit |
b00eeb |
PROP_WARNING,
|
|
Packit |
b00eeb |
PROP_PASSWORD_NEW,
|
|
Packit |
b00eeb |
PROP_PASSWORD_STRENGTH,
|
|
Packit |
b00eeb |
PROP_CHOICE_LABEL,
|
|
Packit |
b00eeb |
PROP_CHOICE_CHOSEN,
|
|
Packit |
b00eeb |
PROP_CALLER_WINDOW,
|
|
Packit |
b00eeb |
PROP_CONTINUE_LABEL,
|
|
Packit |
b00eeb |
PROP_CANCEL_LABEL
|
|
Packit |
b00eeb |
};
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
struct _GcrSystemPromptPrivate {
|
|
Packit |
b00eeb |
gchar *prompter_bus_name;
|
|
Packit |
b00eeb |
GcrSecretExchange *exchange;
|
|
Packit |
b00eeb |
gboolean received;
|
|
Packit |
b00eeb |
GHashTable *properties;
|
|
Packit |
b00eeb |
GHashTable *dirty_properties;
|
|
Packit |
b00eeb |
gint timeout_seconds;
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
GDBusConnection *connection;
|
|
Packit |
b00eeb |
gboolean begun_prompting;
|
|
Packit |
b00eeb |
gboolean closed;
|
|
Packit |
b00eeb |
guint prompt_registered;
|
|
Packit |
b00eeb |
gchar *prompt_path;
|
|
Packit |
b00eeb |
gchar *prompt_owner;
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
GSimpleAsyncResult *pending;
|
|
Packit |
b00eeb |
gchar *last_response;
|
|
Packit |
b00eeb |
};
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
static void gcr_system_prompt_prompt_iface (GcrPromptIface *iface);
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
static void gcr_system_prompt_initable_iface (GInitableIface *iface);
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
static void gcr_system_prompt_async_initable_iface (GAsyncInitableIface *iface);
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
static void perform_init_async (GcrSystemPrompt *self,
|
|
Packit |
b00eeb |
GSimpleAsyncResult *res);
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
G_DEFINE_TYPE_WITH_CODE (GcrSystemPrompt, gcr_system_prompt, G_TYPE_OBJECT,
|
|
Packit |
b00eeb |
G_IMPLEMENT_INTERFACE (GCR_TYPE_PROMPT, gcr_system_prompt_prompt_iface);
|
|
Packit |
b00eeb |
G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE, gcr_system_prompt_initable_iface);
|
|
Packit |
b00eeb |
G_IMPLEMENT_INTERFACE (G_TYPE_ASYNC_INITABLE, gcr_system_prompt_async_initable_iface);
|
|
Packit |
b00eeb |
);
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
static gint unique_prompt_id = 0;
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
typedef struct {
|
|
Packit |
b00eeb |
GSource *timeout;
|
|
Packit |
b00eeb |
GSource *waiting;
|
|
Packit |
b00eeb |
GMainContext *context;
|
|
Packit |
b00eeb |
GCancellable *cancellable;
|
|
Packit |
b00eeb |
guint watch_id;
|
|
Packit |
b00eeb |
} CallClosure;
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
static void
|
|
Packit |
b00eeb |
call_closure_free (gpointer data)
|
|
Packit |
b00eeb |
{
|
|
Packit |
b00eeb |
CallClosure *closure = data;
|
|
Packit |
b00eeb |
if (closure->timeout) {
|
|
Packit |
b00eeb |
g_source_destroy (closure->timeout);
|
|
Packit |
b00eeb |
g_source_unref (closure->timeout);
|
|
Packit |
b00eeb |
}
|
|
Packit |
b00eeb |
if (closure->waiting) {
|
|
Packit |
b00eeb |
g_source_destroy (closure->waiting);
|
|
Packit |
b00eeb |
g_source_unref (closure->waiting);
|
|
Packit |
b00eeb |
}
|
|
Packit |
b00eeb |
if (closure->watch_id)
|
|
Packit |
b00eeb |
g_bus_unwatch_name (closure->watch_id);
|
|
Packit |
b00eeb |
g_object_unref (closure->cancellable);
|
|
Packit |
b00eeb |
g_free (data);
|
|
Packit |
b00eeb |
}
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
static void
|
|
Packit |
b00eeb |
on_propagate_cancelled (GCancellable *cancellable,
|
|
Packit |
b00eeb |
gpointer user_data)
|
|
Packit |
b00eeb |
{
|
|
Packit |
b00eeb |
/* Propagate the cancelled signal */
|
|
Packit |
b00eeb |
GCancellable *cancel = G_CANCELLABLE (user_data);
|
|
Packit |
b00eeb |
g_cancellable_cancel (cancel);
|
|
Packit |
b00eeb |
}
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
static CallClosure *
|
|
Packit |
b00eeb |
call_closure_new (GCancellable *cancellable)
|
|
Packit |
b00eeb |
{
|
|
Packit |
b00eeb |
CallClosure *call;
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
/*
|
|
Packit |
b00eeb |
* We use our own cancellable object, since we cancel it it in
|
|
Packit |
b00eeb |
* situations other than when the caller cancels.
|
|
Packit |
b00eeb |
*/
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
call = g_new0 (CallClosure, 1);
|
|
Packit |
b00eeb |
call->cancellable = g_cancellable_new ();
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
if (cancellable) {
|
|
Packit |
b00eeb |
g_cancellable_connect (cancellable, G_CALLBACK (on_propagate_cancelled),
|
|
Packit |
b00eeb |
g_object_ref (call->cancellable), g_object_unref);
|
|
Packit |
b00eeb |
}
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
return call;
|
|
Packit |
b00eeb |
}
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
static void
|
|
Packit |
b00eeb |
gcr_system_prompt_init (GcrSystemPrompt *self)
|
|
Packit |
b00eeb |
{
|
|
Packit |
b00eeb |
self->pv = G_TYPE_INSTANCE_GET_PRIVATE (self, GCR_TYPE_SYSTEM_PROMPT,
|
|
Packit |
b00eeb |
GcrSystemPromptPrivate);
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
self->pv->timeout_seconds = -1;
|
|
Packit |
b00eeb |
self->pv->properties = g_hash_table_new_full (g_direct_hash, g_direct_equal,
|
|
Packit |
b00eeb |
NULL, (GDestroyNotify)g_variant_unref);
|
|
Packit |
b00eeb |
self->pv->dirty_properties = g_hash_table_new (g_direct_hash, g_direct_equal);
|
|
Packit |
b00eeb |
}
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
static const gchar *
|
|
Packit |
b00eeb |
prompt_get_string_property (GcrSystemPrompt *self,
|
|
Packit |
b00eeb |
const gchar *property_name,
|
|
Packit |
b00eeb |
gboolean collapse_empty_to_null)
|
|
Packit |
b00eeb |
{
|
|
Packit |
b00eeb |
const gchar *value = NULL;
|
|
Packit |
b00eeb |
GVariant *variant;
|
|
Packit |
b00eeb |
gconstpointer key;
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
g_return_val_if_fail (GCR_IS_SYSTEM_PROMPT (self), NULL);
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
key = g_intern_string (property_name);
|
|
Packit |
b00eeb |
variant = g_hash_table_lookup (self->pv->properties, key);
|
|
Packit |
b00eeb |
if (variant != NULL) {
|
|
Packit |
b00eeb |
value = g_variant_get_string (variant, NULL);
|
|
Packit |
b00eeb |
if (collapse_empty_to_null && value != NULL && value[0] == '\0')
|
|
Packit |
b00eeb |
value = NULL;
|
|
Packit |
b00eeb |
}
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
return value;
|
|
Packit |
b00eeb |
}
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
static void
|
|
Packit |
b00eeb |
prompt_set_string_property (GcrSystemPrompt *self,
|
|
Packit |
b00eeb |
const gchar *property_name,
|
|
Packit |
b00eeb |
const gchar *value)
|
|
Packit |
b00eeb |
{
|
|
Packit |
b00eeb |
GVariant *variant;
|
|
Packit |
b00eeb |
gpointer key;
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
g_return_if_fail (GCR_IS_SYSTEM_PROMPT (self));
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
key = (gpointer)g_intern_string (property_name);
|
|
Packit |
b00eeb |
variant = g_variant_ref_sink (g_variant_new_string (value ? value : ""));
|
|
Packit |
b00eeb |
g_hash_table_insert (self->pv->properties, key, variant);
|
|
Packit |
b00eeb |
g_hash_table_insert (self->pv->dirty_properties, key, key);
|
|
Packit |
b00eeb |
g_object_notify (G_OBJECT (self), property_name);
|
|
Packit |
b00eeb |
}
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
static gint
|
|
Packit |
b00eeb |
prompt_get_int_property (GcrSystemPrompt *self,
|
|
Packit |
b00eeb |
const gchar *property_name)
|
|
Packit |
b00eeb |
{
|
|
Packit |
b00eeb |
GVariant *variant;
|
|
Packit |
b00eeb |
gconstpointer key;
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
g_return_val_if_fail (GCR_IS_SYSTEM_PROMPT (self), 0);
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
key = g_intern_string (property_name);
|
|
Packit |
b00eeb |
variant = g_hash_table_lookup (self->pv->properties, key);
|
|
Packit |
b00eeb |
if (variant != NULL)
|
|
Packit |
b00eeb |
return g_variant_get_int32 (variant);
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
return 0;
|
|
Packit |
b00eeb |
}
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
static gboolean
|
|
Packit |
b00eeb |
prompt_get_boolean_property (GcrSystemPrompt *self,
|
|
Packit |
b00eeb |
const gchar *property_name)
|
|
Packit |
b00eeb |
{
|
|
Packit |
b00eeb |
GVariant *variant;
|
|
Packit |
b00eeb |
gconstpointer key;
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
g_return_val_if_fail (GCR_IS_SYSTEM_PROMPT (self), FALSE);
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
key = g_intern_string (property_name);
|
|
Packit |
b00eeb |
variant = g_hash_table_lookup (self->pv->properties, key);
|
|
Packit |
b00eeb |
if (variant != NULL)
|
|
Packit |
b00eeb |
return g_variant_get_boolean (variant);
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
return FALSE;
|
|
Packit |
b00eeb |
}
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
static void
|
|
Packit |
b00eeb |
prompt_set_boolean_property (GcrSystemPrompt *self,
|
|
Packit |
b00eeb |
const gchar *property_name,
|
|
Packit |
b00eeb |
gboolean value)
|
|
Packit |
b00eeb |
{
|
|
Packit |
b00eeb |
GVariant *variant;
|
|
Packit |
b00eeb |
gpointer key;
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
g_return_if_fail (GCR_IS_SYSTEM_PROMPT (self));
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
key = (gpointer)g_intern_string (property_name);
|
|
Packit |
b00eeb |
variant = g_variant_ref_sink (g_variant_new_boolean (value));
|
|
Packit |
b00eeb |
g_hash_table_insert (self->pv->properties, key, variant);
|
|
Packit |
b00eeb |
g_hash_table_insert (self->pv->dirty_properties, key, key);
|
|
Packit |
b00eeb |
g_object_notify (G_OBJECT (self), property_name);
|
|
Packit |
b00eeb |
}
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
static void
|
|
Packit |
b00eeb |
gcr_system_prompt_set_property (GObject *obj,
|
|
Packit |
b00eeb |
guint prop_id,
|
|
Packit |
b00eeb |
const GValue *value,
|
|
Packit |
b00eeb |
GParamSpec *pspec)
|
|
Packit |
b00eeb |
{
|
|
Packit |
b00eeb |
GcrSystemPrompt *self = GCR_SYSTEM_PROMPT (obj);
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
switch (prop_id) {
|
|
Packit |
b00eeb |
case PROP_BUS_NAME:
|
|
Packit |
b00eeb |
g_assert (self->pv->prompter_bus_name == NULL);
|
|
Packit |
b00eeb |
self->pv->prompter_bus_name = g_value_dup_string (value);
|
|
Packit |
b00eeb |
break;
|
|
Packit |
b00eeb |
case PROP_SECRET_EXCHANGE:
|
|
Packit |
b00eeb |
if (self->pv->exchange) {
|
|
Packit |
b00eeb |
g_warning ("The secret exchange is already in use, and cannot be changed");
|
|
Packit |
b00eeb |
return;
|
|
Packit |
b00eeb |
}
|
|
Packit |
b00eeb |
self->pv->exchange = g_value_dup_object (value);
|
|
Packit |
b00eeb |
g_object_notify (G_OBJECT (self), "secret-exchange");
|
|
Packit |
b00eeb |
break;
|
|
Packit |
b00eeb |
case PROP_TIMEOUT_SECONDS:
|
|
Packit |
b00eeb |
self->pv->timeout_seconds = g_value_get_int (value);
|
|
Packit |
b00eeb |
break;
|
|
Packit |
b00eeb |
case PROP_TITLE:
|
|
Packit |
b00eeb |
prompt_set_string_property (self, "title", g_value_get_string (value));
|
|
Packit |
b00eeb |
break;
|
|
Packit |
b00eeb |
case PROP_MESSAGE:
|
|
Packit |
b00eeb |
prompt_set_string_property (self, "message", g_value_get_string (value));
|
|
Packit |
b00eeb |
break;
|
|
Packit |
b00eeb |
case PROP_DESCRIPTION:
|
|
Packit |
b00eeb |
prompt_set_string_property (self, "description", g_value_get_string (value));
|
|
Packit |
b00eeb |
break;
|
|
Packit |
b00eeb |
case PROP_WARNING:
|
|
Packit |
b00eeb |
prompt_set_string_property (self, "warning", g_value_get_string (value));
|
|
Packit |
b00eeb |
break;
|
|
Packit |
b00eeb |
case PROP_PASSWORD_NEW:
|
|
Packit |
b00eeb |
prompt_set_boolean_property (self, "password-new", g_value_get_boolean (value));
|
|
Packit |
b00eeb |
break;
|
|
Packit |
b00eeb |
case PROP_CHOICE_LABEL:
|
|
Packit |
b00eeb |
prompt_set_string_property (self, "choice-label", g_value_get_string (value));
|
|
Packit |
b00eeb |
break;
|
|
Packit |
b00eeb |
case PROP_CHOICE_CHOSEN:
|
|
Packit |
b00eeb |
prompt_set_boolean_property (self, "choice-chosen", g_value_get_boolean (value));
|
|
Packit |
b00eeb |
break;
|
|
Packit |
b00eeb |
case PROP_CALLER_WINDOW:
|
|
Packit |
b00eeb |
prompt_set_string_property (self, "caller-window", g_value_get_string (value));
|
|
Packit |
b00eeb |
break;
|
|
Packit |
b00eeb |
case PROP_CONTINUE_LABEL:
|
|
Packit |
b00eeb |
prompt_set_string_property (self, "continue-label", g_value_get_string (value));
|
|
Packit |
b00eeb |
break;
|
|
Packit |
b00eeb |
case PROP_CANCEL_LABEL:
|
|
Packit |
b00eeb |
prompt_set_string_property (self, "cancel-label", g_value_get_string (value));
|
|
Packit |
b00eeb |
break;
|
|
Packit |
b00eeb |
default:
|
|
Packit |
b00eeb |
G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, prop_id, pspec);
|
|
Packit |
b00eeb |
break;
|
|
Packit |
b00eeb |
}
|
|
Packit |
b00eeb |
}
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
static void
|
|
Packit |
b00eeb |
gcr_system_prompt_get_property (GObject *obj,
|
|
Packit |
b00eeb |
guint prop_id,
|
|
Packit |
b00eeb |
GValue *value,
|
|
Packit |
b00eeb |
GParamSpec *pspec)
|
|
Packit |
b00eeb |
{
|
|
Packit |
b00eeb |
GcrSystemPrompt *self = GCR_SYSTEM_PROMPT (obj);
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
switch (prop_id) {
|
|
Packit |
b00eeb |
case PROP_BUS_NAME:
|
|
Packit |
b00eeb |
g_value_set_string (value, self->pv->prompter_bus_name);
|
|
Packit |
b00eeb |
break;
|
|
Packit |
b00eeb |
case PROP_SECRET_EXCHANGE:
|
|
Packit |
b00eeb |
g_value_set_object (value, gcr_system_prompt_get_secret_exchange (self));
|
|
Packit |
b00eeb |
break;
|
|
Packit |
b00eeb |
case PROP_TITLE:
|
|
Packit |
b00eeb |
g_value_set_string (value, prompt_get_string_property (self, "title", FALSE));
|
|
Packit |
b00eeb |
break;
|
|
Packit |
b00eeb |
case PROP_MESSAGE:
|
|
Packit |
b00eeb |
g_value_set_string (value, prompt_get_string_property (self, "message", FALSE));
|
|
Packit |
b00eeb |
break;
|
|
Packit |
b00eeb |
case PROP_DESCRIPTION:
|
|
Packit |
b00eeb |
g_value_set_string (value, prompt_get_string_property (self, "description", FALSE));
|
|
Packit |
b00eeb |
break;
|
|
Packit |
b00eeb |
case PROP_WARNING:
|
|
Packit |
b00eeb |
g_value_set_string (value, prompt_get_string_property (self, "warning", TRUE));
|
|
Packit |
b00eeb |
break;
|
|
Packit |
b00eeb |
case PROP_PASSWORD_NEW:
|
|
Packit |
b00eeb |
g_value_set_boolean (value, prompt_get_boolean_property (self, "password-new"));
|
|
Packit |
b00eeb |
break;
|
|
Packit |
b00eeb |
case PROP_PASSWORD_STRENGTH:
|
|
Packit |
b00eeb |
g_value_set_int (value, prompt_get_int_property (self, "password-strength"));
|
|
Packit |
b00eeb |
break;
|
|
Packit |
b00eeb |
case PROP_CHOICE_LABEL:
|
|
Packit |
b00eeb |
g_value_set_string (value, prompt_get_string_property (self, "choice-label", TRUE));
|
|
Packit |
b00eeb |
break;
|
|
Packit |
b00eeb |
case PROP_CHOICE_CHOSEN:
|
|
Packit |
b00eeb |
g_value_set_boolean (value, prompt_get_boolean_property (self, "choice-chosen"));
|
|
Packit |
b00eeb |
break;
|
|
Packit |
b00eeb |
case PROP_CALLER_WINDOW:
|
|
Packit |
b00eeb |
g_value_set_string (value, prompt_get_string_property (self, "caller-window", TRUE));
|
|
Packit |
b00eeb |
break;
|
|
Packit |
b00eeb |
case PROP_CONTINUE_LABEL:
|
|
Packit |
b00eeb |
g_value_set_string (value, prompt_get_string_property (self, "continue-label", TRUE));
|
|
Packit |
b00eeb |
break;
|
|
Packit |
b00eeb |
case PROP_CANCEL_LABEL:
|
|
Packit |
b00eeb |
g_value_set_string (value, prompt_get_string_property (self, "cancel-label", TRUE));
|
|
Packit |
b00eeb |
break;
|
|
Packit |
b00eeb |
default:
|
|
Packit |
b00eeb |
G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, prop_id, pspec);
|
|
Packit |
b00eeb |
break;
|
|
Packit |
b00eeb |
}
|
|
Packit |
b00eeb |
}
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
static void
|
|
Packit |
b00eeb |
gcr_system_prompt_constructed (GObject *obj)
|
|
Packit |
b00eeb |
{
|
|
Packit |
b00eeb |
GcrSystemPrompt *self = GCR_SYSTEM_PROMPT (obj);
|
|
Packit |
b00eeb |
gint seed;
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
G_OBJECT_CLASS (gcr_system_prompt_parent_class)->constructed (obj);
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
seed = g_atomic_int_add (&unique_prompt_id, 1);
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
self->pv->prompt_path = g_strdup_printf ("%s/p%d", GCR_DBUS_PROMPT_OBJECT_PREFIX, seed);
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
if (self->pv->prompter_bus_name == NULL)
|
|
Packit |
b00eeb |
self->pv->prompter_bus_name = g_strdup (GCR_DBUS_PROMPTER_SYSTEM_BUS_NAME);
|
|
Packit |
b00eeb |
}
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
static void
|
|
Packit |
b00eeb |
on_prompter_stop_prompting (GObject *source,
|
|
Packit |
b00eeb |
GAsyncResult *result,
|
|
Packit |
b00eeb |
gpointer user_data)
|
|
Packit |
b00eeb |
{
|
|
Packit |
b00eeb |
GSimpleAsyncResult *async = NULL;
|
|
Packit |
b00eeb |
GError *error = NULL;
|
|
Packit |
b00eeb |
GVariant *retval;
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
retval = g_dbus_connection_call_finish (G_DBUS_CONNECTION (source), result, &error);
|
|
Packit |
b00eeb |
if (error != NULL) {
|
|
Packit |
b00eeb |
g_debug ("failed to stop prompting: %s", egg_error_message (error));
|
|
Packit |
b00eeb |
g_clear_error (&error);
|
|
Packit |
b00eeb |
}
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
if (retval)
|
|
Packit |
b00eeb |
g_variant_unref (retval);
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
if (user_data) {
|
|
Packit |
b00eeb |
async = G_SIMPLE_ASYNC_RESULT (user_data);
|
|
Packit |
b00eeb |
g_simple_async_result_complete (async);
|
|
Packit |
b00eeb |
g_object_unref (async);
|
|
Packit |
b00eeb |
}
|
|
Packit |
b00eeb |
}
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
static void
|
|
Packit |
b00eeb |
perform_close (GcrSystemPrompt *self,
|
|
Packit |
b00eeb |
GSimpleAsyncResult *async,
|
|
Packit |
b00eeb |
GCancellable *cancellable)
|
|
Packit |
b00eeb |
{
|
|
Packit |
b00eeb |
GSimpleAsyncResult *res;
|
|
Packit |
b00eeb |
CallClosure *closure;
|
|
Packit |
b00eeb |
gboolean called = FALSE;
|
|
Packit |
b00eeb |
gboolean closed;
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
closed = self->pv->closed;
|
|
Packit |
b00eeb |
self->pv->closed = TRUE;
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
if (!closed)
|
|
Packit |
b00eeb |
g_debug ("closing prompt");
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
if (self->pv->pending) {
|
|
Packit |
b00eeb |
res = g_object_ref (self->pv->pending);
|
|
Packit |
b00eeb |
g_clear_object (&self->pv->pending);
|
|
Packit |
b00eeb |
closure = g_simple_async_result_get_op_res_gpointer (res);
|
|
Packit |
b00eeb |
g_cancellable_cancel (closure->cancellable);
|
|
Packit |
b00eeb |
g_simple_async_result_complete_in_idle (res);
|
|
Packit |
b00eeb |
g_object_unref (res);
|
|
Packit |
b00eeb |
}
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
if (self->pv->prompt_registered) {
|
|
Packit |
b00eeb |
g_dbus_connection_unregister_object (self->pv->connection,
|
|
Packit |
b00eeb |
self->pv->prompt_registered);
|
|
Packit |
b00eeb |
self->pv->prompt_registered = 0;
|
|
Packit |
b00eeb |
}
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
if (self->pv->begun_prompting) {
|
|
Packit |
b00eeb |
if (self->pv->connection && self->pv->prompt_path && self->pv->prompt_owner) {
|
|
Packit |
b00eeb |
g_debug ("Calling the prompter %s method", GCR_DBUS_PROMPTER_METHOD_STOP);
|
|
Packit |
b00eeb |
g_dbus_connection_call (self->pv->connection,
|
|
Packit |
b00eeb |
self->pv->prompter_bus_name,
|
|
Packit |
b00eeb |
GCR_DBUS_PROMPTER_OBJECT_PATH,
|
|
Packit |
b00eeb |
GCR_DBUS_PROMPTER_INTERFACE,
|
|
Packit |
b00eeb |
GCR_DBUS_PROMPTER_METHOD_STOP,
|
|
Packit |
b00eeb |
g_variant_new ("(o)", self->pv->prompt_path),
|
|
Packit |
b00eeb |
G_VARIANT_TYPE ("()"),
|
|
Packit |
b00eeb |
G_DBUS_CALL_FLAGS_NO_AUTO_START,
|
|
Packit |
b00eeb |
-1, cancellable,
|
|
Packit |
b00eeb |
on_prompter_stop_prompting,
|
|
Packit |
b00eeb |
async ? g_object_ref (async) : NULL);
|
|
Packit |
b00eeb |
called = TRUE;
|
|
Packit |
b00eeb |
}
|
|
Packit |
b00eeb |
self->pv->begun_prompting = FALSE;
|
|
Packit |
b00eeb |
}
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
g_free (self->pv->prompt_path);
|
|
Packit |
b00eeb |
self->pv->prompt_path = NULL;
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
g_clear_object (&self->pv->connection);
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
if (!called && async)
|
|
Packit |
b00eeb |
g_simple_async_result_complete_in_idle (async);
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
/* Emit the signal if necessary, after closed */
|
|
Packit |
b00eeb |
if (!closed)
|
|
Packit |
b00eeb |
gcr_prompt_close (GCR_PROMPT (self));
|
|
Packit |
b00eeb |
}
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
static void
|
|
Packit |
b00eeb |
gcr_system_prompt_dispose (GObject *obj)
|
|
Packit |
b00eeb |
{
|
|
Packit |
b00eeb |
GcrSystemPrompt *self = GCR_SYSTEM_PROMPT (obj);
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
g_clear_object (&self->pv->exchange);
|
|
Packit |
b00eeb |
perform_close (self, NULL, NULL);
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
g_hash_table_remove_all (self->pv->properties);
|
|
Packit |
b00eeb |
g_hash_table_remove_all (self->pv->dirty_properties);
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
G_OBJECT_CLASS (gcr_system_prompt_parent_class)->dispose (obj);
|
|
Packit |
b00eeb |
}
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
static void
|
|
Packit |
b00eeb |
gcr_system_prompt_finalize (GObject *obj)
|
|
Packit |
b00eeb |
{
|
|
Packit |
b00eeb |
GcrSystemPrompt *self = GCR_SYSTEM_PROMPT (obj);
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
g_free (self->pv->prompter_bus_name);
|
|
Packit |
b00eeb |
g_free (self->pv->prompt_owner);
|
|
Packit |
b00eeb |
g_free (self->pv->last_response);
|
|
Packit |
b00eeb |
g_hash_table_destroy (self->pv->properties);
|
|
Packit |
b00eeb |
g_hash_table_destroy (self->pv->dirty_properties);
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
G_OBJECT_CLASS (gcr_system_prompt_parent_class)->finalize (obj);
|
|
Packit |
b00eeb |
}
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
static void
|
|
Packit |
b00eeb |
gcr_system_prompt_class_init (GcrSystemPromptClass *klass)
|
|
Packit |
b00eeb |
{
|
|
Packit |
b00eeb |
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
gobject_class->constructed = gcr_system_prompt_constructed;
|
|
Packit |
b00eeb |
gobject_class->get_property = gcr_system_prompt_get_property;
|
|
Packit |
b00eeb |
gobject_class->set_property = gcr_system_prompt_set_property;
|
|
Packit |
b00eeb |
gobject_class->dispose = gcr_system_prompt_dispose;
|
|
Packit |
b00eeb |
gobject_class->finalize = gcr_system_prompt_finalize;
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
g_type_class_add_private (gobject_class, sizeof (GcrSystemPromptPrivate));
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
/**
|
|
Packit |
b00eeb |
* GcrSystemPrompt:bus-name:
|
|
Packit |
b00eeb |
*
|
|
Packit |
b00eeb |
* The DBus bus name of the prompter to use for prompting, or %NULL
|
|
Packit |
b00eeb |
* for the default prompter.
|
|
Packit |
b00eeb |
*/
|
|
Packit |
b00eeb |
g_object_class_install_property (gobject_class, PROP_BUS_NAME,
|
|
Packit |
b00eeb |
g_param_spec_string ("bus-name", "Bus name", "Prompter bus name",
|
|
Packit |
b00eeb |
NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
/**
|
|
Packit |
b00eeb |
* GcrSystemPrompt:timeout-seconds:
|
|
Packit |
b00eeb |
*
|
|
Packit |
b00eeb |
* The timeout in seconds to wait when opening the prompt.
|
|
Packit |
b00eeb |
*/
|
|
Packit |
b00eeb |
g_object_class_install_property (gobject_class, PROP_TIMEOUT_SECONDS,
|
|
Packit |
b00eeb |
g_param_spec_int ("timeout-seconds", "Timeout seconds", "Timeout (in seconds) for opening prompt",
|
|
Packit |
b00eeb |
-1, G_MAXINT, -1, G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY));
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
/**
|
|
Packit |
b00eeb |
* GcrSystemPrompt:secret-exchange:
|
|
Packit |
b00eeb |
*
|
|
Packit |
b00eeb |
* The #GcrSecretExchange to use when transferring passwords. A default
|
|
Packit |
b00eeb |
* secret exchange will be used if this is not set.
|
|
Packit |
b00eeb |
*/
|
|
Packit |
b00eeb |
g_object_class_install_property (gobject_class, PROP_SECRET_EXCHANGE,
|
|
Packit |
b00eeb |
g_param_spec_object ("secret-exchange", "Secret exchange", "Secret exchange for passing passwords",
|
|
Packit |
b00eeb |
GCR_TYPE_SECRET_EXCHANGE, G_PARAM_READWRITE));
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
g_object_class_override_property (gobject_class, PROP_TITLE, "title");
|
|
Packit |
b00eeb |
g_object_class_override_property (gobject_class, PROP_MESSAGE, "message");
|
|
Packit |
b00eeb |
g_object_class_override_property (gobject_class, PROP_DESCRIPTION, "description");
|
|
Packit |
b00eeb |
g_object_class_override_property (gobject_class, PROP_WARNING, "warning");
|
|
Packit |
b00eeb |
g_object_class_override_property (gobject_class, PROP_PASSWORD_NEW, "password-new");
|
|
Packit |
b00eeb |
g_object_class_override_property (gobject_class, PROP_PASSWORD_STRENGTH, "password-strength");
|
|
Packit |
b00eeb |
g_object_class_override_property (gobject_class, PROP_CHOICE_LABEL, "choice-label");
|
|
Packit |
b00eeb |
g_object_class_override_property (gobject_class, PROP_CHOICE_CHOSEN, "choice-chosen");
|
|
Packit |
b00eeb |
g_object_class_override_property (gobject_class, PROP_CALLER_WINDOW, "caller-window");
|
|
Packit |
b00eeb |
g_object_class_override_property (gobject_class, PROP_CONTINUE_LABEL, "continue-label");
|
|
Packit |
b00eeb |
g_object_class_override_property (gobject_class, PROP_CANCEL_LABEL, "cancel-label");
|
|
Packit |
b00eeb |
}
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
/**
|
|
Packit |
b00eeb |
* gcr_system_prompt_get_secret_exchange:
|
|
Packit |
b00eeb |
* @self: a prompter
|
|
Packit |
b00eeb |
*
|
|
Packit |
b00eeb |
* Get the current #GcrSecretExchange used to transfer secrets in this prompt.
|
|
Packit |
b00eeb |
*
|
|
Packit |
b00eeb |
* Returns: (transfer none): the secret exchange
|
|
Packit |
b00eeb |
*/
|
|
Packit |
b00eeb |
GcrSecretExchange *
|
|
Packit |
b00eeb |
gcr_system_prompt_get_secret_exchange (GcrSystemPrompt *self)
|
|
Packit |
b00eeb |
{
|
|
Packit |
b00eeb |
g_return_val_if_fail (GCR_IS_SYSTEM_PROMPT (self), NULL);
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
if (!self->pv->exchange) {
|
|
Packit |
b00eeb |
g_debug ("creating new secret exchange");
|
|
Packit |
b00eeb |
self->pv->exchange = gcr_secret_exchange_new (NULL);
|
|
Packit |
b00eeb |
}
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
return self->pv->exchange;
|
|
Packit |
b00eeb |
}
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
static void
|
|
Packit |
b00eeb |
update_properties_from_iter (GcrSystemPrompt *self,
|
|
Packit |
b00eeb |
GVariantIter *iter)
|
|
Packit |
b00eeb |
{
|
|
Packit |
b00eeb |
GObject *obj = G_OBJECT (self);
|
|
Packit |
b00eeb |
GVariant *variant;
|
|
Packit |
b00eeb |
GVariant *value;
|
|
Packit |
b00eeb |
GVariant *already;
|
|
Packit |
b00eeb |
gpointer key;
|
|
Packit |
b00eeb |
gchar *name;
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
g_object_freeze_notify (obj);
|
|
Packit |
b00eeb |
while (g_variant_iter_loop (iter, "{sv}", &name, &variant)) {
|
|
Packit |
b00eeb |
key = (gpointer)g_intern_string (name);
|
|
Packit |
b00eeb |
value = g_variant_get_variant (variant);
|
|
Packit |
b00eeb |
already = g_hash_table_lookup (self->pv->properties, key);
|
|
Packit |
b00eeb |
if (!already || !g_variant_equal (already, value)) {
|
|
Packit |
b00eeb |
g_hash_table_replace (self->pv->properties, key, g_variant_ref (value));
|
|
Packit |
b00eeb |
g_object_notify (obj, name);
|
|
Packit |
b00eeb |
}
|
|
Packit |
b00eeb |
g_variant_unref (value);
|
|
Packit |
b00eeb |
}
|
|
Packit |
b00eeb |
g_object_thaw_notify (obj);
|
|
Packit |
b00eeb |
}
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
static void
|
|
Packit |
b00eeb |
prompt_method_ready (GcrSystemPrompt *self,
|
|
Packit |
b00eeb |
GDBusMethodInvocation *invocation,
|
|
Packit |
b00eeb |
GVariant *parameters)
|
|
Packit |
b00eeb |
{
|
|
Packit |
b00eeb |
GcrSecretExchange *exchange;
|
|
Packit |
b00eeb |
GSimpleAsyncResult *res;
|
|
Packit |
b00eeb |
GVariantIter *iter;
|
|
Packit |
b00eeb |
gchar *received;
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
g_return_if_fail (G_IS_SIMPLE_ASYNC_RESULT (self->pv->pending));
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
g_free (self->pv->last_response);
|
|
Packit |
b00eeb |
g_variant_get (parameters, "(sa{sv}s)",
|
|
Packit |
b00eeb |
&self->pv->last_response,
|
|
Packit |
b00eeb |
&iter, &received);
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
g_dbus_method_invocation_return_value (invocation, g_variant_new ("()"));
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
update_properties_from_iter (self, iter);
|
|
Packit |
b00eeb |
g_variant_iter_free (iter);
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
exchange = gcr_system_prompt_get_secret_exchange (self);
|
|
Packit |
b00eeb |
if (gcr_secret_exchange_receive (exchange, received))
|
|
Packit |
b00eeb |
self->pv->received = TRUE;
|
|
Packit |
b00eeb |
else
|
|
Packit |
b00eeb |
g_warning ("received invalid secret exchange string");
|
|
Packit |
b00eeb |
g_free (received);
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
res = g_object_ref (self->pv->pending);
|
|
Packit |
b00eeb |
g_clear_object (&self->pv->pending);
|
|
Packit |
b00eeb |
g_simple_async_result_complete (res);
|
|
Packit |
b00eeb |
g_object_unref (res);
|
|
Packit |
b00eeb |
}
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
static void
|
|
Packit |
b00eeb |
prompt_method_done (GcrSystemPrompt *self,
|
|
Packit |
b00eeb |
GDBusMethodInvocation *invocation,
|
|
Packit |
b00eeb |
GVariant *parameters)
|
|
Packit |
b00eeb |
{
|
|
Packit |
b00eeb |
g_dbus_method_invocation_return_value (invocation, g_variant_new ("()"));
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
/*
|
|
Packit |
b00eeb |
* At this point we're done prompting, and calling StopPrompting
|
|
Packit |
b00eeb |
* on the prompter is no longer necessary. It may have already been
|
|
Packit |
b00eeb |
* called, or the prompter may have stopped on its own accord.
|
|
Packit |
b00eeb |
*/
|
|
Packit |
b00eeb |
self->pv->begun_prompting = FALSE;
|
|
Packit |
b00eeb |
perform_close (self, NULL, NULL);
|
|
Packit |
b00eeb |
}
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
static void
|
|
Packit |
b00eeb |
prompt_method_call (GDBusConnection *connection,
|
|
Packit |
b00eeb |
const gchar *sender,
|
|
Packit |
b00eeb |
const gchar *object_path,
|
|
Packit |
b00eeb |
const gchar *interface_name,
|
|
Packit |
b00eeb |
const gchar *method_name,
|
|
Packit |
b00eeb |
GVariant *parameters,
|
|
Packit |
b00eeb |
GDBusMethodInvocation *invocation,
|
|
Packit |
b00eeb |
gpointer user_data)
|
|
Packit |
b00eeb |
{
|
|
Packit |
b00eeb |
GcrSystemPrompt *self = GCR_SYSTEM_PROMPT (user_data);
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
g_return_if_fail (method_name != NULL);
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
if (g_str_equal (method_name, GCR_DBUS_CALLBACK_METHOD_READY)) {
|
|
Packit |
b00eeb |
prompt_method_ready (self, invocation, parameters);
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
} else if (g_str_equal (method_name, GCR_DBUS_CALLBACK_METHOD_DONE)) {
|
|
Packit |
b00eeb |
prompt_method_done (self, invocation, parameters);
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
} else {
|
|
Packit |
b00eeb |
g_return_if_reached ();
|
|
Packit |
b00eeb |
}
|
|
Packit |
b00eeb |
}
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
static GVariant *
|
|
Packit |
b00eeb |
prompt_get_property (GDBusConnection *connection,
|
|
Packit |
b00eeb |
const gchar *sender,
|
|
Packit |
b00eeb |
const gchar *object_path,
|
|
Packit |
b00eeb |
const gchar *interface_name,
|
|
Packit |
b00eeb |
const gchar *property_name,
|
|
Packit |
b00eeb |
GError **error,
|
|
Packit |
b00eeb |
gpointer user_data)
|
|
Packit |
b00eeb |
{
|
|
Packit |
b00eeb |
g_return_val_if_reached (NULL);
|
|
Packit |
b00eeb |
}
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
static gboolean
|
|
Packit |
b00eeb |
prompt_set_property (GDBusConnection *connection,
|
|
Packit |
b00eeb |
const gchar *sender,
|
|
Packit |
b00eeb |
const gchar *object_path,
|
|
Packit |
b00eeb |
const gchar *interface_name,
|
|
Packit |
b00eeb |
const gchar *property_name,
|
|
Packit |
b00eeb |
GVariant *value,
|
|
Packit |
b00eeb |
GError **error,
|
|
Packit |
b00eeb |
gpointer user_data)
|
|
Packit |
b00eeb |
{
|
|
Packit |
b00eeb |
g_return_val_if_reached (FALSE);
|
|
Packit |
b00eeb |
}
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
static GDBusInterfaceVTable prompt_dbus_vtable = {
|
|
Packit |
b00eeb |
prompt_method_call,
|
|
Packit |
b00eeb |
prompt_get_property,
|
|
Packit |
b00eeb |
prompt_set_property,
|
|
Packit |
b00eeb |
};
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
static void
|
|
Packit |
b00eeb |
register_prompt_object (GcrSystemPrompt *self,
|
|
Packit |
b00eeb |
GError **error)
|
|
Packit |
b00eeb |
{
|
|
Packit |
b00eeb |
GError *lerror = NULL;
|
|
Packit |
b00eeb |
guint id;
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
/*
|
|
Packit |
b00eeb |
* The unregister/reregister allows us to register this under a whatever
|
|
Packit |
b00eeb |
* GMainContext has been pushed as the thread default context.
|
|
Packit |
b00eeb |
*/
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
if (self->pv->prompt_registered)
|
|
Packit |
b00eeb |
g_dbus_connection_unregister_object (self->pv->connection,
|
|
Packit |
b00eeb |
self->pv->prompt_registered);
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
id = g_dbus_connection_register_object (self->pv->connection,
|
|
Packit |
b00eeb |
self->pv->prompt_path,
|
|
Packit |
b00eeb |
_gcr_dbus_prompter_callback_interface_info (),
|
|
Packit |
b00eeb |
&prompt_dbus_vtable,
|
|
Packit |
b00eeb |
self, NULL, &lerror);
|
|
Packit |
b00eeb |
self->pv->prompt_registered = id;
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
if (lerror != NULL) {
|
|
Packit |
b00eeb |
g_warning ("error registering prompter %s", egg_error_message (lerror));
|
|
Packit |
b00eeb |
g_propagate_error (error, lerror);
|
|
Packit |
b00eeb |
}
|
|
Packit |
b00eeb |
}
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
static void
|
|
Packit |
b00eeb |
on_prompter_present (GDBusConnection *connection,
|
|
Packit |
b00eeb |
const gchar *name,
|
|
Packit |
b00eeb |
const gchar *name_owner,
|
|
Packit |
b00eeb |
gpointer user_data)
|
|
Packit |
b00eeb |
{
|
|
Packit |
b00eeb |
GcrSystemPrompt *self = GCR_SYSTEM_PROMPT (g_async_result_get_source_object (user_data));
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
g_free (self->pv->prompt_owner);
|
|
Packit |
b00eeb |
self->pv->prompt_owner = g_strdup (name_owner);
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
g_object_unref (self);
|
|
Packit |
b00eeb |
}
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
static void
|
|
Packit |
b00eeb |
on_prompter_vanished (GDBusConnection *connection,
|
|
Packit |
b00eeb |
const gchar *name,
|
|
Packit |
b00eeb |
gpointer user_data)
|
|
Packit |
b00eeb |
{
|
|
Packit |
b00eeb |
GcrSystemPrompt *self = GCR_SYSTEM_PROMPT (g_async_result_get_source_object (user_data));
|
|
Packit |
b00eeb |
CallClosure *call = g_simple_async_result_get_op_res_gpointer (user_data);
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
if (self->pv->prompt_owner) {
|
|
Packit |
b00eeb |
g_free (self->pv->prompt_owner);
|
|
Packit |
b00eeb |
self->pv->prompt_owner = NULL;
|
|
Packit |
b00eeb |
g_debug ("prompter name owner has vanished: %s", name);
|
|
Packit |
b00eeb |
g_cancellable_cancel (call->cancellable);
|
|
Packit |
b00eeb |
}
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
g_object_unref (self);
|
|
Packit |
b00eeb |
}
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
static void
|
|
Packit |
b00eeb |
on_bus_connected (GObject *source,
|
|
Packit |
b00eeb |
GAsyncResult *result,
|
|
Packit |
b00eeb |
gpointer user_data)
|
|
Packit |
b00eeb |
{
|
|
Packit |
b00eeb |
GSimpleAsyncResult *res = G_SIMPLE_ASYNC_RESULT (user_data);
|
|
Packit |
b00eeb |
GcrSystemPrompt *self = GCR_SYSTEM_PROMPT (g_async_result_get_source_object (user_data));
|
|
Packit |
b00eeb |
CallClosure *closure = g_simple_async_result_get_op_res_gpointer (res);
|
|
Packit |
b00eeb |
GError *error = NULL;
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
g_assert (self->pv->connection == NULL);
|
|
Packit |
b00eeb |
self->pv->connection = g_bus_get_finish (result, &error);
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
if (error != NULL) {
|
|
Packit |
b00eeb |
g_debug ("failed to connect to bus: %s", egg_error_message (error));
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
} else {
|
|
Packit |
b00eeb |
g_return_if_fail (self->pv->connection != NULL);
|
|
Packit |
b00eeb |
g_debug ("connected to bus");
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
g_main_context_push_thread_default (closure->context);
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
closure->watch_id = g_bus_watch_name_on_connection (self->pv->connection,
|
|
Packit |
b00eeb |
self->pv->prompter_bus_name,
|
|
Packit |
b00eeb |
G_BUS_NAME_WATCHER_FLAGS_NONE,
|
|
Packit |
b00eeb |
on_prompter_present,
|
|
Packit |
b00eeb |
on_prompter_vanished,
|
|
Packit |
b00eeb |
res, NULL);
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
register_prompt_object (self, &error);
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
g_main_context_pop_thread_default (closure->context);
|
|
Packit |
b00eeb |
}
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
if (error == NULL) {
|
|
Packit |
b00eeb |
perform_init_async (self, res);
|
|
Packit |
b00eeb |
} else {
|
|
Packit |
b00eeb |
g_simple_async_result_take_error (res, error);
|
|
Packit |
b00eeb |
g_simple_async_result_complete (res);
|
|
Packit |
b00eeb |
}
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
g_object_unref (self);
|
|
Packit |
b00eeb |
g_object_unref (res);
|
|
Packit |
b00eeb |
}
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
static void
|
|
Packit |
b00eeb |
on_prompter_begin_prompting (GObject *source,
|
|
Packit |
b00eeb |
GAsyncResult *result,
|
|
Packit |
b00eeb |
gpointer user_data)
|
|
Packit |
b00eeb |
{
|
|
Packit |
b00eeb |
GSimpleAsyncResult *res = G_SIMPLE_ASYNC_RESULT (user_data);
|
|
Packit |
b00eeb |
GcrSystemPrompt *self = GCR_SYSTEM_PROMPT (g_async_result_get_source_object (user_data));
|
|
Packit |
b00eeb |
GError *error = NULL;
|
|
Packit |
b00eeb |
GVariant *ret;
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
ret = g_dbus_connection_call_finish (self->pv->connection, result, &error);
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
if (error == NULL) {
|
|
Packit |
b00eeb |
self->pv->begun_prompting = TRUE;
|
|
Packit |
b00eeb |
g_variant_unref (ret);
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
g_debug ("registered prompt %s: %s",
|
|
Packit |
b00eeb |
self->pv->prompter_bus_name, self->pv->prompt_path);
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
g_return_if_fail (self->pv->prompt_path != NULL);
|
|
Packit |
b00eeb |
perform_init_async (self, res);
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
} else {
|
|
Packit |
b00eeb |
g_debug ("failed to register prompt %s: %s",
|
|
Packit |
b00eeb |
self->pv->prompter_bus_name, egg_error_message (error));
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
g_simple_async_result_take_error (res, error);
|
|
Packit |
b00eeb |
g_simple_async_result_complete (res);
|
|
Packit |
b00eeb |
}
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
g_object_unref (self);
|
|
Packit |
b00eeb |
g_object_unref (res);
|
|
Packit |
b00eeb |
}
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
static gboolean
|
|
Packit |
b00eeb |
on_call_timeout (gpointer user_data)
|
|
Packit |
b00eeb |
{
|
|
Packit |
b00eeb |
GSimpleAsyncResult *res = G_SIMPLE_ASYNC_RESULT (user_data);
|
|
Packit |
b00eeb |
CallClosure *closure = g_simple_async_result_get_op_res_gpointer (res);
|
|
Packit |
b00eeb |
GcrSystemPrompt *self = GCR_SYSTEM_PROMPT (g_async_result_get_source_object (user_data));
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
g_source_destroy (closure->timeout);
|
|
Packit |
b00eeb |
g_source_unref (closure->timeout);
|
|
Packit |
b00eeb |
closure->timeout = NULL;
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
/* Tell the prompter we're no longer interested */
|
|
Packit |
b00eeb |
gcr_system_prompt_close_async (self, NULL, NULL, NULL);
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
g_simple_async_result_set_error (res, GCR_SYSTEM_PROMPT_ERROR,
|
|
Packit |
b00eeb |
GCR_SYSTEM_PROMPT_IN_PROGRESS,
|
|
Packit |
b00eeb |
_("Another prompt is already in progress"));
|
|
Packit |
b00eeb |
g_simple_async_result_complete (res);
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
g_object_unref (self);
|
|
Packit |
b00eeb |
return FALSE; /* Don't call this function again */
|
|
Packit |
b00eeb |
}
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
static gboolean
|
|
Packit |
b00eeb |
on_call_cancelled (GCancellable *cancellable,
|
|
Packit |
b00eeb |
gpointer user_data)
|
|
Packit |
b00eeb |
{
|
|
Packit |
b00eeb |
GSimpleAsyncResult *async = G_SIMPLE_ASYNC_RESULT (user_data);
|
|
Packit |
b00eeb |
CallClosure *call = g_simple_async_result_get_op_res_gpointer (async);
|
|
Packit |
b00eeb |
GcrSystemPrompt *self = GCR_SYSTEM_PROMPT (g_async_result_get_source_object (user_data));
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
g_source_destroy (call->waiting);
|
|
Packit |
b00eeb |
g_source_unref (call->waiting);
|
|
Packit |
b00eeb |
call->waiting = NULL;
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
g_simple_async_result_set_error (async, G_IO_ERROR, G_IO_ERROR_CANCELLED,
|
|
Packit |
b00eeb |
_("The operation was cancelled"));
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
/* Tell the prompter we're no longer interested */
|
|
Packit |
b00eeb |
gcr_system_prompt_close_async (self, NULL, NULL, NULL);
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
g_object_unref (self);
|
|
Packit |
b00eeb |
return FALSE; /* Don't call this function again */
|
|
Packit |
b00eeb |
}
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
void
|
|
Packit |
b00eeb |
perform_init_async (GcrSystemPrompt *self,
|
|
Packit |
b00eeb |
GSimpleAsyncResult *res)
|
|
Packit |
b00eeb |
{
|
|
Packit |
b00eeb |
CallClosure *closure = g_simple_async_result_get_op_res_gpointer (res);
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
g_main_context_push_thread_default (closure->context);
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
/* 1. Connect to the session bus */
|
|
Packit |
b00eeb |
if (!self->pv->connection) {
|
|
Packit |
b00eeb |
g_debug ("connecting to bus");
|
|
Packit |
b00eeb |
g_bus_get (G_BUS_TYPE_SESSION, closure->cancellable,
|
|
Packit |
b00eeb |
on_bus_connected, g_object_ref (res));
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
/* 2. Export our object, BeginPrompting on prompter */
|
|
Packit |
b00eeb |
} else if (!self->pv->begun_prompting) {
|
|
Packit |
b00eeb |
g_assert (self->pv->prompt_path != NULL);
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
g_debug ("calling %s method on prompter", GCR_DBUS_PROMPTER_METHOD_BEGIN);
|
|
Packit |
b00eeb |
g_dbus_connection_call (self->pv->connection,
|
|
Packit |
b00eeb |
self->pv->prompter_bus_name,
|
|
Packit |
b00eeb |
GCR_DBUS_PROMPTER_OBJECT_PATH,
|
|
Packit |
b00eeb |
GCR_DBUS_PROMPTER_INTERFACE,
|
|
Packit |
b00eeb |
GCR_DBUS_PROMPTER_METHOD_BEGIN,
|
|
Packit |
b00eeb |
g_variant_new ("(o)", self->pv->prompt_path),
|
|
Packit |
b00eeb |
G_VARIANT_TYPE ("()"),
|
|
Packit |
b00eeb |
G_DBUS_CALL_FLAGS_NONE,
|
|
Packit |
b00eeb |
-1, closure->cancellable,
|
|
Packit |
b00eeb |
on_prompter_begin_prompting,
|
|
Packit |
b00eeb |
g_object_ref (res));
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
/* 3. Wait for iterate */
|
|
Packit |
b00eeb |
} else if (!self->pv->pending) {
|
|
Packit |
b00eeb |
self->pv->pending = g_object_ref (res);
|
|
Packit |
b00eeb |
if (self->pv->timeout_seconds > 0) {
|
|
Packit |
b00eeb |
g_assert (closure->timeout == NULL);
|
|
Packit |
b00eeb |
closure->timeout = g_timeout_source_new_seconds (self->pv->timeout_seconds);
|
|
Packit |
b00eeb |
g_source_set_callback (closure->timeout, on_call_timeout, res, NULL);
|
|
Packit |
b00eeb |
g_source_attach (closure->timeout, closure->context);
|
|
Packit |
b00eeb |
}
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
g_assert (closure->waiting == NULL);
|
|
Packit |
b00eeb |
closure->waiting = g_cancellable_source_new (closure->cancellable);
|
|
Packit |
b00eeb |
g_source_set_callback (closure->waiting, (GSourceFunc)on_call_cancelled, res, NULL);
|
|
Packit |
b00eeb |
g_source_attach (closure->waiting, closure->context);
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
/* 4. All done */
|
|
Packit |
b00eeb |
} else {
|
|
Packit |
b00eeb |
g_assert_not_reached ();
|
|
Packit |
b00eeb |
}
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
g_main_context_pop_thread_default (closure->context);
|
|
Packit |
b00eeb |
}
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
static void
|
|
Packit |
b00eeb |
gcr_system_prompt_real_init_async (GAsyncInitable *initable,
|
|
Packit |
b00eeb |
int io_priority,
|
|
Packit |
b00eeb |
GCancellable *cancellable,
|
|
Packit |
b00eeb |
GAsyncReadyCallback callback,
|
|
Packit |
b00eeb |
gpointer user_data)
|
|
Packit |
b00eeb |
{
|
|
Packit |
b00eeb |
GcrSystemPrompt *self = GCR_SYSTEM_PROMPT (initable);
|
|
Packit |
b00eeb |
GSimpleAsyncResult *res;
|
|
Packit |
b00eeb |
CallClosure *closure;
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
res = g_simple_async_result_new (G_OBJECT (self), callback, user_data,
|
|
Packit |
b00eeb |
gcr_system_prompt_real_init_async);
|
|
Packit |
b00eeb |
closure = call_closure_new (cancellable);
|
|
Packit |
b00eeb |
closure->context = g_main_context_get_thread_default ();
|
|
Packit |
b00eeb |
if (closure->context)
|
|
Packit |
b00eeb |
g_main_context_ref (closure->context);
|
|
Packit |
b00eeb |
g_simple_async_result_set_op_res_gpointer (res, closure, call_closure_free);
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
perform_init_async (self, res);
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
g_object_unref (res);
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
}
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
static gboolean
|
|
Packit |
b00eeb |
gcr_system_prompt_real_init_finish (GAsyncInitable *initable,
|
|
Packit |
b00eeb |
GAsyncResult *result,
|
|
Packit |
b00eeb |
GError **error)
|
|
Packit |
b00eeb |
{
|
|
Packit |
b00eeb |
GcrSystemPrompt *self = GCR_SYSTEM_PROMPT (initable);
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (self),
|
|
Packit |
b00eeb |
gcr_system_prompt_real_init_async), FALSE);
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (result), error))
|
|
Packit |
b00eeb |
return FALSE;
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
return TRUE;
|
|
Packit |
b00eeb |
}
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
static void
|
|
Packit |
b00eeb |
gcr_system_prompt_async_initable_iface (GAsyncInitableIface *iface)
|
|
Packit |
b00eeb |
{
|
|
Packit |
b00eeb |
iface->init_async = gcr_system_prompt_real_init_async;
|
|
Packit |
b00eeb |
iface->init_finish = gcr_system_prompt_real_init_finish;
|
|
Packit |
b00eeb |
}
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
typedef struct {
|
|
Packit |
b00eeb |
GAsyncResult *result;
|
|
Packit |
b00eeb |
GMainContext *context;
|
|
Packit |
b00eeb |
GMainLoop *loop;
|
|
Packit |
b00eeb |
} SyncClosure;
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
static SyncClosure *
|
|
Packit |
b00eeb |
sync_closure_new (void)
|
|
Packit |
b00eeb |
{
|
|
Packit |
b00eeb |
SyncClosure *closure;
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
closure = g_new0 (SyncClosure, 1);
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
closure->context = g_main_context_new ();
|
|
Packit |
b00eeb |
closure->loop = g_main_loop_new (closure->context, FALSE);
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
return closure;
|
|
Packit |
b00eeb |
}
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
static void
|
|
Packit |
b00eeb |
sync_closure_free (gpointer data)
|
|
Packit |
b00eeb |
{
|
|
Packit |
b00eeb |
SyncClosure *closure = data;
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
g_clear_object (&closure->result);
|
|
Packit |
b00eeb |
g_main_loop_unref (closure->loop);
|
|
Packit |
b00eeb |
g_main_context_unref (closure->context);
|
|
Packit |
b00eeb |
g_free (closure);
|
|
Packit |
b00eeb |
}
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
static void
|
|
Packit |
b00eeb |
on_sync_result (GObject *source,
|
|
Packit |
b00eeb |
GAsyncResult *result,
|
|
Packit |
b00eeb |
gpointer user_data)
|
|
Packit |
b00eeb |
{
|
|
Packit |
b00eeb |
SyncClosure *closure = user_data;
|
|
Packit |
b00eeb |
closure->result = g_object_ref (result);
|
|
Packit |
b00eeb |
g_main_loop_quit (closure->loop);
|
|
Packit |
b00eeb |
}
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
static gboolean
|
|
Packit |
b00eeb |
gcr_system_prompt_real_init (GInitable *initable,
|
|
Packit |
b00eeb |
GCancellable *cancellable,
|
|
Packit |
b00eeb |
GError **error)
|
|
Packit |
b00eeb |
{
|
|
Packit |
b00eeb |
SyncClosure *closure;
|
|
Packit |
b00eeb |
gboolean result;
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
closure = sync_closure_new ();
|
|
Packit |
b00eeb |
g_main_context_push_thread_default (closure->context);
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
gcr_system_prompt_real_init_async (G_ASYNC_INITABLE (initable),
|
|
Packit |
b00eeb |
G_PRIORITY_DEFAULT, cancellable,
|
|
Packit |
b00eeb |
on_sync_result, closure);
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
g_main_loop_run (closure->loop);
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
result = gcr_system_prompt_real_init_finish (G_ASYNC_INITABLE (initable),
|
|
Packit |
b00eeb |
closure->result, error);
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
g_main_context_pop_thread_default (closure->context);
|
|
Packit |
b00eeb |
sync_closure_free (closure);
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
return result;
|
|
Packit |
b00eeb |
}
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
static void
|
|
Packit |
b00eeb |
gcr_system_prompt_initable_iface (GInitableIface *iface)
|
|
Packit |
b00eeb |
{
|
|
Packit |
b00eeb |
iface->init = gcr_system_prompt_real_init;
|
|
Packit |
b00eeb |
}
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
static GVariantBuilder *
|
|
Packit |
b00eeb |
build_dirty_properties (GcrSystemPrompt *self)
|
|
Packit |
b00eeb |
{
|
|
Packit |
b00eeb |
GVariantBuilder *builder;
|
|
Packit |
b00eeb |
GHashTableIter iter;
|
|
Packit |
b00eeb |
GVariant *variant;
|
|
Packit |
b00eeb |
gpointer key;
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
builder = g_variant_builder_new (G_VARIANT_TYPE ("a{sv}"));
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
g_hash_table_iter_init (&iter, self->pv->dirty_properties);
|
|
Packit |
b00eeb |
while (g_hash_table_iter_next (&iter, &key, NULL)) {
|
|
Packit |
b00eeb |
variant = g_hash_table_lookup (self->pv->properties, key);
|
|
Packit |
b00eeb |
g_variant_builder_add (builder, "{sv}", (const gchar *)key, variant);
|
|
Packit |
b00eeb |
}
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
g_hash_table_remove_all (self->pv->dirty_properties);
|
|
Packit |
b00eeb |
return builder;
|
|
Packit |
b00eeb |
}
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
static void
|
|
Packit |
b00eeb |
on_perform_prompt_complete (GObject *source,
|
|
Packit |
b00eeb |
GAsyncResult *result,
|
|
Packit |
b00eeb |
gpointer user_data)
|
|
Packit |
b00eeb |
{
|
|
Packit |
b00eeb |
GSimpleAsyncResult *res = G_SIMPLE_ASYNC_RESULT (user_data);
|
|
Packit |
b00eeb |
GcrSystemPrompt *self = GCR_SYSTEM_PROMPT (g_async_result_get_source_object (user_data));
|
|
Packit |
b00eeb |
CallClosure *call = g_simple_async_result_get_op_res_gpointer (res);
|
|
Packit |
b00eeb |
GError *error = NULL;
|
|
Packit |
b00eeb |
GVariant *retval;
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
retval = g_dbus_connection_call_finish (G_DBUS_CONNECTION (source), result, &error);
|
|
Packit |
b00eeb |
if (error != NULL) {
|
|
Packit |
b00eeb |
self->pv->pending = NULL;
|
|
Packit |
b00eeb |
g_simple_async_result_take_error (res, error);
|
|
Packit |
b00eeb |
g_simple_async_result_complete (res);
|
|
Packit |
b00eeb |
} else {
|
|
Packit |
b00eeb |
g_assert (call->waiting == NULL);
|
|
Packit |
b00eeb |
call->waiting = g_cancellable_source_new (call->cancellable);
|
|
Packit |
b00eeb |
g_source_set_callback (call->waiting, (GSourceFunc)on_call_cancelled, res, NULL);
|
|
Packit |
b00eeb |
g_source_attach (call->waiting, call->context);
|
|
Packit |
b00eeb |
}
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
if (retval)
|
|
Packit |
b00eeb |
g_variant_unref (retval);
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
g_object_unref (self);
|
|
Packit |
b00eeb |
g_object_unref (res);
|
|
Packit |
b00eeb |
}
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
static void
|
|
Packit |
b00eeb |
perform_prompt_async (GcrSystemPrompt *self,
|
|
Packit |
b00eeb |
const gchar *type,
|
|
Packit |
b00eeb |
gpointer source_tag,
|
|
Packit |
b00eeb |
GCancellable *cancellable,
|
|
Packit |
b00eeb |
GAsyncReadyCallback callback,
|
|
Packit |
b00eeb |
gpointer user_data)
|
|
Packit |
b00eeb |
{
|
|
Packit |
b00eeb |
GSimpleAsyncResult *res;
|
|
Packit |
b00eeb |
GcrSecretExchange *exchange;
|
|
Packit |
b00eeb |
GVariantBuilder *builder;
|
|
Packit |
b00eeb |
CallClosure *closure;
|
|
Packit |
b00eeb |
gchar *sent;
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
g_return_if_fail (GCR_IS_SYSTEM_PROMPT (self));
|
|
Packit |
b00eeb |
g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
if (self->pv->pending != NULL) {
|
|
Packit |
b00eeb |
g_warning ("another operation is already pending on this prompt");
|
|
Packit |
b00eeb |
return;
|
|
Packit |
b00eeb |
}
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
res = g_simple_async_result_new (G_OBJECT (self), callback, user_data, source_tag);
|
|
Packit |
b00eeb |
closure = call_closure_new (cancellable);
|
|
Packit |
b00eeb |
g_simple_async_result_set_op_res_gpointer (res, closure, call_closure_free);
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
if (self->pv->closed) {
|
|
Packit |
b00eeb |
g_free (self->pv->last_response);
|
|
Packit |
b00eeb |
self->pv->last_response = g_strdup (GCR_DBUS_PROMPT_REPLY_NONE);
|
|
Packit |
b00eeb |
g_simple_async_result_complete_in_idle (res);
|
|
Packit |
b00eeb |
g_object_unref (res);
|
|
Packit |
b00eeb |
return;
|
|
Packit |
b00eeb |
}
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
g_debug ("prompting for password");
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
exchange = gcr_system_prompt_get_secret_exchange (self);
|
|
Packit |
b00eeb |
if (self->pv->received)
|
|
Packit |
b00eeb |
sent = gcr_secret_exchange_send (exchange, NULL, 0);
|
|
Packit |
b00eeb |
else
|
|
Packit |
b00eeb |
sent = gcr_secret_exchange_begin (exchange);
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
closure->watch_id = g_bus_watch_name_on_connection (self->pv->connection,
|
|
Packit |
b00eeb |
self->pv->prompter_bus_name,
|
|
Packit |
b00eeb |
G_BUS_NAME_WATCHER_FLAGS_NONE,
|
|
Packit |
b00eeb |
on_prompter_present,
|
|
Packit |
b00eeb |
on_prompter_vanished,
|
|
Packit |
b00eeb |
res, NULL);
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
builder = build_dirty_properties (self);
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
/* Reregister the prompt object in the current GMainContext */
|
|
Packit |
b00eeb |
register_prompt_object (self, NULL);
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
g_dbus_connection_call (self->pv->connection,
|
|
Packit |
b00eeb |
self->pv->prompter_bus_name,
|
|
Packit |
b00eeb |
GCR_DBUS_PROMPTER_OBJECT_PATH,
|
|
Packit |
b00eeb |
GCR_DBUS_PROMPTER_INTERFACE,
|
|
Packit |
b00eeb |
GCR_DBUS_PROMPTER_METHOD_PERFORM,
|
|
Packit |
b00eeb |
g_variant_new ("(osa{sv}s)", self->pv->prompt_path,
|
|
Packit |
b00eeb |
type, builder, sent),
|
|
Packit |
b00eeb |
G_VARIANT_TYPE ("()"),
|
|
Packit |
b00eeb |
G_DBUS_CALL_FLAGS_NO_AUTO_START,
|
|
Packit |
b00eeb |
-1, cancellable,
|
|
Packit |
b00eeb |
on_perform_prompt_complete,
|
|
Packit |
b00eeb |
g_object_ref (res));
|
|
Packit |
b00eeb |
g_variant_builder_unref(builder);
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
self->pv->pending = res;
|
|
Packit |
b00eeb |
g_free (sent);
|
|
Packit |
b00eeb |
}
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
static GcrPromptReply
|
|
Packit |
b00eeb |
handle_last_response (GcrSystemPrompt *self)
|
|
Packit |
b00eeb |
{
|
|
Packit |
b00eeb |
GcrPromptReply response;
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
g_return_val_if_fail (self->pv->last_response != NULL,
|
|
Packit |
b00eeb |
GCR_PROMPT_REPLY_CANCEL);
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
if (g_str_equal (self->pv->last_response, GCR_DBUS_PROMPT_REPLY_YES)) {
|
|
Packit |
b00eeb |
response = GCR_PROMPT_REPLY_CONTINUE;
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
} else if (g_str_equal (self->pv->last_response, GCR_DBUS_PROMPT_REPLY_NO) ||
|
|
Packit |
b00eeb |
g_str_equal (self->pv->last_response, GCR_DBUS_PROMPT_REPLY_NONE)) {
|
|
Packit |
b00eeb |
response = GCR_PROMPT_REPLY_CANCEL;
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
} else {
|
|
Packit |
b00eeb |
g_warning ("unknown response from prompter: %s", self->pv->last_response);
|
|
Packit |
b00eeb |
response = GCR_PROMPT_REPLY_CANCEL;
|
|
Packit |
b00eeb |
}
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
return response;
|
|
Packit |
b00eeb |
}
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
static void
|
|
Packit |
b00eeb |
gcr_system_prompt_password_async (GcrPrompt *prompt,
|
|
Packit |
b00eeb |
GCancellable *cancellable,
|
|
Packit |
b00eeb |
GAsyncReadyCallback callback,
|
|
Packit |
b00eeb |
gpointer user_data)
|
|
Packit |
b00eeb |
{
|
|
Packit |
b00eeb |
GcrSystemPrompt *self = GCR_SYSTEM_PROMPT (prompt);
|
|
Packit |
b00eeb |
perform_prompt_async (self, GCR_DBUS_PROMPT_TYPE_PASSWORD,
|
|
Packit |
b00eeb |
gcr_system_prompt_password_async,
|
|
Packit |
b00eeb |
cancellable, callback, user_data);
|
|
Packit |
b00eeb |
}
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
static const gchar *
|
|
Packit |
b00eeb |
gcr_system_prompt_password_finish (GcrPrompt *prompt,
|
|
Packit |
b00eeb |
GAsyncResult *result,
|
|
Packit |
b00eeb |
GError **error)
|
|
Packit |
b00eeb |
{
|
|
Packit |
b00eeb |
GcrSystemPrompt *self = GCR_SYSTEM_PROMPT (prompt);
|
|
Packit |
b00eeb |
GSimpleAsyncResult *res;
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (self),
|
|
Packit |
b00eeb |
gcr_system_prompt_password_async), FALSE);
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
res = G_SIMPLE_ASYNC_RESULT (result);
|
|
Packit |
b00eeb |
if (g_simple_async_result_propagate_error (res, error))
|
|
Packit |
b00eeb |
return FALSE;
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
if (handle_last_response (self) == GCR_PROMPT_REPLY_CONTINUE)
|
|
Packit |
b00eeb |
return gcr_secret_exchange_get_secret (self->pv->exchange, NULL);
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
return NULL;
|
|
Packit |
b00eeb |
}
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
static void
|
|
Packit |
b00eeb |
gcr_system_prompt_confirm_async (GcrPrompt *prompt,
|
|
Packit |
b00eeb |
GCancellable *cancellable,
|
|
Packit |
b00eeb |
GAsyncReadyCallback callback,
|
|
Packit |
b00eeb |
gpointer user_data)
|
|
Packit |
b00eeb |
{
|
|
Packit |
b00eeb |
GcrSystemPrompt *self = GCR_SYSTEM_PROMPT (prompt);
|
|
Packit |
b00eeb |
perform_prompt_async (self, GCR_DBUS_PROMPT_TYPE_CONFIRM,
|
|
Packit |
b00eeb |
gcr_system_prompt_confirm_async,
|
|
Packit |
b00eeb |
cancellable, callback, user_data);
|
|
Packit |
b00eeb |
}
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
static GcrPromptReply
|
|
Packit |
b00eeb |
gcr_system_prompt_confirm_finish (GcrPrompt *prompt,
|
|
Packit |
b00eeb |
GAsyncResult *result,
|
|
Packit |
b00eeb |
GError **error)
|
|
Packit |
b00eeb |
{
|
|
Packit |
b00eeb |
GcrSystemPrompt *self = GCR_SYSTEM_PROMPT (prompt);
|
|
Packit |
b00eeb |
GSimpleAsyncResult *res;
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
g_return_val_if_fail (GCR_IS_SYSTEM_PROMPT (self), FALSE);
|
|
Packit |
b00eeb |
g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (self),
|
|
Packit |
b00eeb |
gcr_system_prompt_confirm_async), FALSE);
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
res = G_SIMPLE_ASYNC_RESULT (result);
|
|
Packit |
b00eeb |
if (g_simple_async_result_propagate_error (res, error))
|
|
Packit |
b00eeb |
return FALSE;
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
return handle_last_response (self);
|
|
Packit |
b00eeb |
}
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
static void
|
|
Packit |
b00eeb |
gcr_system_prompt_real_close (GcrPrompt *prompt)
|
|
Packit |
b00eeb |
{
|
|
Packit |
b00eeb |
GcrSystemPrompt *self = GCR_SYSTEM_PROMPT (prompt);
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
/*
|
|
Packit |
b00eeb |
* Setting this before calling close_async allows us to prevent firing
|
|
Packit |
b00eeb |
* this signal again in a loop.
|
|
Packit |
b00eeb |
*/
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
if (!self->pv->closed) {
|
|
Packit |
b00eeb |
self->pv->closed = TRUE;
|
|
Packit |
b00eeb |
perform_close (self, NULL, NULL);
|
|
Packit |
b00eeb |
}
|
|
Packit |
b00eeb |
}
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
static void
|
|
Packit |
b00eeb |
gcr_system_prompt_prompt_iface (GcrPromptIface *iface)
|
|
Packit |
b00eeb |
{
|
|
Packit |
b00eeb |
iface->prompt_password_async = gcr_system_prompt_password_async;
|
|
Packit |
b00eeb |
iface->prompt_password_finish = gcr_system_prompt_password_finish;
|
|
Packit |
b00eeb |
iface->prompt_confirm_async = gcr_system_prompt_confirm_async;
|
|
Packit |
b00eeb |
iface->prompt_confirm_finish = gcr_system_prompt_confirm_finish;
|
|
Packit |
b00eeb |
iface->prompt_close = gcr_system_prompt_real_close;
|
|
Packit |
b00eeb |
}
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
/**
|
|
Packit |
b00eeb |
* gcr_system_prompt_open_async:
|
|
Packit |
b00eeb |
* @timeout_seconds: the number of seconds to wait to access the prompt, or -1
|
|
Packit |
b00eeb |
* @cancellable: optional cancellation object
|
|
Packit |
b00eeb |
* @callback: called when the operation completes
|
|
Packit |
b00eeb |
* @user_data: data to pass the callback
|
|
Packit |
b00eeb |
*
|
|
Packit |
b00eeb |
* Asynchronously open a system prompt with the default system prompter.
|
|
Packit |
b00eeb |
*
|
|
Packit |
b00eeb |
* Most system prompters only allow showing one prompt at a time, and if
|
|
Packit |
b00eeb |
* another prompt is shown then this method will block for up to
|
|
Packit |
b00eeb |
* @timeout_seconds seconds. If @timeout_seconds is equal to -1, then this
|
|
Packit |
b00eeb |
* will block indefinitely until the prompt can be opened. If @timeout_seconds
|
|
Packit |
b00eeb |
* expires, then this operation will fail with a %GCR_SYSTEM_PROMPT_IN_PROGRESS
|
|
Packit |
b00eeb |
* error.
|
|
Packit |
b00eeb |
*/
|
|
Packit |
b00eeb |
void
|
|
Packit |
b00eeb |
gcr_system_prompt_open_async (gint timeout_seconds,
|
|
Packit |
b00eeb |
GCancellable *cancellable,
|
|
Packit |
b00eeb |
GAsyncReadyCallback callback,
|
|
Packit |
b00eeb |
gpointer user_data)
|
|
Packit |
b00eeb |
{
|
|
Packit |
b00eeb |
g_return_if_fail (timeout_seconds >= -1);
|
|
Packit |
b00eeb |
g_return_if_fail (cancellable == NULL || G_CANCELLABLE (cancellable));
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
gcr_system_prompt_open_for_prompter_async (NULL, timeout_seconds,
|
|
Packit |
b00eeb |
cancellable, callback,
|
|
Packit |
b00eeb |
user_data);
|
|
Packit |
b00eeb |
}
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
/**
|
|
Packit |
b00eeb |
* gcr_system_prompt_open_for_prompter_async:
|
|
Packit |
b00eeb |
* @prompter_name: (allow-none): the prompter dbus name
|
|
Packit |
b00eeb |
* @timeout_seconds: the number of seconds to wait to access the prompt, or -1
|
|
Packit |
b00eeb |
* @cancellable: optional cancellation object
|
|
Packit |
b00eeb |
* @callback: called when the operation completes
|
|
Packit |
b00eeb |
* @user_data: data to pass the callback
|
|
Packit |
b00eeb |
*
|
|
Packit |
b00eeb |
* Opens a system prompt asynchronously. If prompter_name is %NULL, then the
|
|
Packit |
b00eeb |
* default system prompter is used.
|
|
Packit |
b00eeb |
*
|
|
Packit |
b00eeb |
* Most system prompters only allow showing one prompt at a time, and if
|
|
Packit |
b00eeb |
* another prompt is shown then this method will block for up to
|
|
Packit |
b00eeb |
* @timeout_seconds seconds. If @timeout_seconds is equal to -1, then this
|
|
Packit |
b00eeb |
* will block indefinitely until the prompt can be opened. If @timeout_seconds
|
|
Packit |
b00eeb |
* expires, then this operation will fail with a %GCR_SYSTEM_PROMPT_IN_PROGRESS
|
|
Packit |
b00eeb |
* error.
|
|
Packit |
b00eeb |
*/
|
|
Packit |
b00eeb |
void
|
|
Packit |
b00eeb |
gcr_system_prompt_open_for_prompter_async (const gchar *prompter_name,
|
|
Packit |
b00eeb |
gint timeout_seconds,
|
|
Packit |
b00eeb |
GCancellable *cancellable,
|
|
Packit |
b00eeb |
GAsyncReadyCallback callback,
|
|
Packit |
b00eeb |
gpointer user_data)
|
|
Packit |
b00eeb |
{
|
|
Packit |
b00eeb |
g_return_if_fail (timeout_seconds >= -1);
|
|
Packit |
b00eeb |
g_return_if_fail (cancellable == NULL || G_CANCELLABLE (cancellable));
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
if (prompter_name == NULL)
|
|
Packit |
b00eeb |
g_debug ("opening prompt");
|
|
Packit |
b00eeb |
else
|
|
Packit |
b00eeb |
g_debug ("opening prompt for prompter: %s", prompter_name);
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
g_async_initable_new_async (GCR_TYPE_SYSTEM_PROMPT,
|
|
Packit |
b00eeb |
G_PRIORITY_DEFAULT,
|
|
Packit |
b00eeb |
cancellable,
|
|
Packit |
b00eeb |
callback,
|
|
Packit |
b00eeb |
user_data,
|
|
Packit |
b00eeb |
"timeout-seconds", timeout_seconds,
|
|
Packit |
b00eeb |
"bus-name", prompter_name,
|
|
Packit |
b00eeb |
NULL);
|
|
Packit |
b00eeb |
}
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
/**
|
|
Packit |
b00eeb |
* gcr_system_prompt_open_finish:
|
|
Packit |
b00eeb |
* @result: the asynchronous result
|
|
Packit |
b00eeb |
* @error: location to place an error on failure
|
|
Packit |
b00eeb |
*
|
|
Packit |
b00eeb |
* Complete an operation to asynchronously open a system prompt.
|
|
Packit |
b00eeb |
*
|
|
Packit |
b00eeb |
* Returns: (transfer full) (type Gcr.SystemPrompt): the prompt, or %NULL if
|
|
Packit |
b00eeb |
* prompt could not be opened
|
|
Packit |
b00eeb |
*/
|
|
Packit |
b00eeb |
GcrPrompt *
|
|
Packit |
b00eeb |
gcr_system_prompt_open_finish (GAsyncResult *result,
|
|
Packit |
b00eeb |
GError **error)
|
|
Packit |
b00eeb |
{
|
|
Packit |
b00eeb |
GObject *object;
|
|
Packit |
b00eeb |
GObject *source_object;
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
g_return_val_if_fail (G_IS_ASYNC_RESULT (result), NULL);
|
|
Packit |
b00eeb |
g_return_val_if_fail (error == NULL || *error == NULL, NULL);
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
source_object = g_async_result_get_source_object (result);
|
|
Packit |
b00eeb |
g_assert (source_object != NULL);
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
object = g_async_initable_new_finish (G_ASYNC_INITABLE (source_object),
|
|
Packit |
b00eeb |
result, error);
|
|
Packit |
b00eeb |
g_object_unref (source_object);
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
if (object != NULL)
|
|
Packit |
b00eeb |
return GCR_PROMPT (object);
|
|
Packit |
b00eeb |
else
|
|
Packit |
b00eeb |
return NULL;
|
|
Packit |
b00eeb |
}
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
/**
|
|
Packit |
b00eeb |
* gcr_system_prompt_open:
|
|
Packit |
b00eeb |
* @timeout_seconds: the number of seconds to wait to access the prompt, or -1
|
|
Packit |
b00eeb |
* @cancellable: optional cancellation object
|
|
Packit |
b00eeb |
* @error: location to place error on failure
|
|
Packit |
b00eeb |
*
|
|
Packit |
b00eeb |
* Opens a system prompt with the default prompter.
|
|
Packit |
b00eeb |
*
|
|
Packit |
b00eeb |
* Most system prompters only allow showing one prompt at a time, and if
|
|
Packit |
b00eeb |
* another prompt is shown then this method will block for up to
|
|
Packit |
b00eeb |
* @timeout_seconds seconds. If @timeout_seconds is equal to -1, then this
|
|
Packit |
b00eeb |
* will block indefinitely until the prompt can be opened. If @timeout_seconds
|
|
Packit |
b00eeb |
* expires, then this function will fail with a %GCR_SYSTEM_PROMPT_IN_PROGRESS
|
|
Packit |
b00eeb |
* error.
|
|
Packit |
b00eeb |
*
|
|
Packit |
b00eeb |
* Returns: (transfer full) (type Gcr.SystemPrompt): the prompt, or %NULL if
|
|
Packit |
b00eeb |
* prompt could not be opened
|
|
Packit |
b00eeb |
*/
|
|
Packit |
b00eeb |
GcrPrompt *
|
|
Packit |
b00eeb |
gcr_system_prompt_open (gint timeout_seconds,
|
|
Packit |
b00eeb |
GCancellable *cancellable,
|
|
Packit |
b00eeb |
GError **error)
|
|
Packit |
b00eeb |
{
|
|
Packit |
b00eeb |
g_return_val_if_fail (timeout_seconds >= -1, NULL);
|
|
Packit |
b00eeb |
g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), NULL);
|
|
Packit |
b00eeb |
g_return_val_if_fail (error == NULL || *error == NULL, NULL);
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
return gcr_system_prompt_open_for_prompter (NULL, timeout_seconds,
|
|
Packit |
b00eeb |
cancellable, error);
|
|
Packit |
b00eeb |
}
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
/**
|
|
Packit |
b00eeb |
* gcr_system_prompt_open_for_prompter:
|
|
Packit |
b00eeb |
* @prompter_name: (allow-none): the prompter dbus name
|
|
Packit |
b00eeb |
* @timeout_seconds: the number of seconds to wait to access the prompt, or -1
|
|
Packit |
b00eeb |
* @cancellable: optional cancellation object
|
|
Packit |
b00eeb |
* @error: location to place error on failure
|
|
Packit |
b00eeb |
*
|
|
Packit |
b00eeb |
* Opens a system prompt. If prompter_name is %NULL, then the default
|
|
Packit |
b00eeb |
* system prompter is used.
|
|
Packit |
b00eeb |
*
|
|
Packit |
b00eeb |
* Most system prompters only allow showing one prompt at a time, and if
|
|
Packit |
b00eeb |
* another prompt is shown then this method will block for up to
|
|
Packit |
b00eeb |
* @timeout_seconds seconds. If @timeout_seconds is equal to -1, then this
|
|
Packit |
b00eeb |
* will block indefinitely until the prompt can be opened. If @timeout_seconds
|
|
Packit |
b00eeb |
* expires, then this function will fail with a %GCR_SYSTEM_PROMPT_IN_PROGRESS
|
|
Packit |
b00eeb |
* error.
|
|
Packit |
b00eeb |
*
|
|
Packit |
b00eeb |
* Returns: (transfer full) (type Gcr.SystemPrompt): the prompt, or %NULL if
|
|
Packit |
b00eeb |
* prompt could not be opened
|
|
Packit |
b00eeb |
*/
|
|
Packit |
b00eeb |
GcrPrompt *
|
|
Packit |
b00eeb |
gcr_system_prompt_open_for_prompter (const gchar *prompter_name,
|
|
Packit |
b00eeb |
gint timeout_seconds,
|
|
Packit |
b00eeb |
GCancellable *cancellable,
|
|
Packit |
b00eeb |
GError **error)
|
|
Packit |
b00eeb |
{
|
|
Packit |
b00eeb |
g_return_val_if_fail (timeout_seconds >= -1, NULL);
|
|
Packit |
b00eeb |
g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), NULL);
|
|
Packit |
b00eeb |
g_return_val_if_fail (error == NULL || *error == NULL, NULL);
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
if (prompter_name == NULL)
|
|
Packit |
b00eeb |
g_debug ("opening prompt");
|
|
Packit |
b00eeb |
else
|
|
Packit |
b00eeb |
g_debug ("opening prompt for prompter: %s", prompter_name);
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
return g_initable_new (GCR_TYPE_SYSTEM_PROMPT, cancellable, error,
|
|
Packit |
b00eeb |
"timeout-seconds", timeout_seconds,
|
|
Packit |
b00eeb |
"bus-name", prompter_name,
|
|
Packit |
b00eeb |
NULL);
|
|
Packit |
b00eeb |
}
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
/**
|
|
Packit |
b00eeb |
* gcr_system_prompt_close:
|
|
Packit |
b00eeb |
* @self: the prompt
|
|
Packit |
b00eeb |
* @cancellable: an optional cancellation object
|
|
Packit |
b00eeb |
* @error: location to place an error on failure
|
|
Packit |
b00eeb |
*
|
|
Packit |
b00eeb |
* Close this prompt. After calling this function, no further prompts will
|
|
Packit |
b00eeb |
* succeed on this object. The prompt object is not unreferenced by this
|
|
Packit |
b00eeb |
* function, and you must unreference it once done.
|
|
Packit |
b00eeb |
*
|
|
Packit |
b00eeb |
* This call may block, use the gcr_system_prompt_close_async() to perform
|
|
Packit |
b00eeb |
* this action indefinitely.
|
|
Packit |
b00eeb |
*
|
|
Packit |
b00eeb |
* Whether or not this function returns %TRUE, the system prompt object is
|
|
Packit |
b00eeb |
* still closed and may not be further used.
|
|
Packit |
b00eeb |
*
|
|
Packit |
b00eeb |
* Returns: whether close was cleanly completed
|
|
Packit |
b00eeb |
*/
|
|
Packit |
b00eeb |
gboolean
|
|
Packit |
b00eeb |
gcr_system_prompt_close (GcrSystemPrompt *self,
|
|
Packit |
b00eeb |
GCancellable *cancellable,
|
|
Packit |
b00eeb |
GError **error)
|
|
Packit |
b00eeb |
{
|
|
Packit |
b00eeb |
SyncClosure *closure;
|
|
Packit |
b00eeb |
gboolean result;
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
closure = sync_closure_new ();
|
|
Packit |
b00eeb |
g_main_context_push_thread_default (closure->context);
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
gcr_system_prompt_close_async (self, cancellable,
|
|
Packit |
b00eeb |
on_sync_result, closure);
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
g_main_loop_run (closure->loop);
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
result = gcr_system_prompt_close_finish (self, closure->result, error);
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
g_main_context_pop_thread_default (closure->context);
|
|
Packit |
b00eeb |
sync_closure_free (closure);
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
return result;
|
|
Packit |
b00eeb |
}
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
/**
|
|
Packit |
b00eeb |
* gcr_system_prompt_close_async:
|
|
Packit |
b00eeb |
* @self: the prompt
|
|
Packit |
b00eeb |
* @cancellable: an optional cancellation object
|
|
Packit |
b00eeb |
* @callback: called when the operation completes
|
|
Packit |
b00eeb |
* @user_data: data to pass to the callback
|
|
Packit |
b00eeb |
*
|
|
Packit |
b00eeb |
* Close this prompt asynchronously. After calling this function, no further
|
|
Packit |
b00eeb |
* methods may be called on this object. The prompt object is not unreferenced
|
|
Packit |
b00eeb |
* by this function, and you must unreference it once done.
|
|
Packit |
b00eeb |
*
|
|
Packit |
b00eeb |
* This call returns immediately and completes asynchronously.
|
|
Packit |
b00eeb |
*/
|
|
Packit |
b00eeb |
void
|
|
Packit |
b00eeb |
gcr_system_prompt_close_async (GcrSystemPrompt *self,
|
|
Packit |
b00eeb |
GCancellable *cancellable,
|
|
Packit |
b00eeb |
GAsyncReadyCallback callback,
|
|
Packit |
b00eeb |
gpointer user_data)
|
|
Packit |
b00eeb |
{
|
|
Packit |
b00eeb |
GSimpleAsyncResult *res;
|
|
Packit |
b00eeb |
CallClosure *closure;
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
g_return_if_fail (GCR_SYSTEM_PROMPT (self));
|
|
Packit |
b00eeb |
g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
res = g_simple_async_result_new (NULL, callback, user_data,
|
|
Packit |
b00eeb |
gcr_system_prompt_close_async);
|
|
Packit |
b00eeb |
closure = call_closure_new (cancellable);
|
|
Packit |
b00eeb |
closure->context = g_main_context_get_thread_default ();
|
|
Packit |
b00eeb |
if (closure->context != NULL)
|
|
Packit |
b00eeb |
g_main_context_ref (closure->context);
|
|
Packit |
b00eeb |
g_simple_async_result_set_op_res_gpointer (res, closure, call_closure_free);
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
perform_close (self, res, closure->cancellable);
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
g_object_unref (res);
|
|
Packit |
b00eeb |
}
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
/**
|
|
Packit |
b00eeb |
* gcr_system_prompt_close_finish:
|
|
Packit |
b00eeb |
* @self: the prompt
|
|
Packit |
b00eeb |
* @result: asynchronous operation result
|
|
Packit |
b00eeb |
* @error: location to place an error on failure
|
|
Packit |
b00eeb |
*
|
|
Packit |
b00eeb |
* Complete operation to close this prompt.
|
|
Packit |
b00eeb |
*
|
|
Packit |
b00eeb |
* Whether or not this function returns %TRUE, the system prompt object is
|
|
Packit |
b00eeb |
* still closed and may not be further used.
|
|
Packit |
b00eeb |
*
|
|
Packit |
b00eeb |
* Returns: whether close was cleanly completed
|
|
Packit |
b00eeb |
*/
|
|
Packit |
b00eeb |
gboolean
|
|
Packit |
b00eeb |
gcr_system_prompt_close_finish (GcrSystemPrompt *self,
|
|
Packit |
b00eeb |
GAsyncResult *result,
|
|
Packit |
b00eeb |
GError **error)
|
|
Packit |
b00eeb |
{
|
|
Packit |
b00eeb |
g_return_val_if_fail (GCR_IS_SYSTEM_PROMPT (self), FALSE);
|
|
Packit |
b00eeb |
g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
g_return_val_if_fail (g_simple_async_result_is_valid (result, NULL,
|
|
Packit |
b00eeb |
gcr_system_prompt_close_async), FALSE);
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (result), error))
|
|
Packit |
b00eeb |
return FALSE;
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
return TRUE;
|
|
Packit |
b00eeb |
}
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
static const GDBusErrorEntry SYSTEM_PROMPT_ERRORS[] = {
|
|
Packit |
b00eeb |
{ GCR_SYSTEM_PROMPT_IN_PROGRESS, GCR_DBUS_PROMPT_ERROR_IN_PROGRESS },
|
|
Packit |
b00eeb |
};
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
GQuark
|
|
Packit |
b00eeb |
gcr_system_prompt_error_get_domain (void)
|
|
Packit |
b00eeb |
{
|
|
Packit |
b00eeb |
static volatile gsize quark_volatile = 0;
|
|
Packit |
b00eeb |
g_dbus_error_register_error_domain ("gcr-system-prompt-error-domain",
|
|
Packit |
b00eeb |
&quark_volatile,
|
|
Packit |
b00eeb |
SYSTEM_PROMPT_ERRORS,
|
|
Packit |
b00eeb |
G_N_ELEMENTS (SYSTEM_PROMPT_ERRORS));
|
|
Packit |
b00eeb |
G_STATIC_ASSERT (G_N_ELEMENTS (SYSTEM_PROMPT_ERRORS) == GCR_SYSTEM_PROMPT_IN_PROGRESS);
|
|
Packit |
b00eeb |
return (GQuark) quark_volatile;
|
|
Packit |
b00eeb |
}
|