/* Wait forever for a system prompt. */
#define SYSTEM_PROMPT_TIMEOUT (-1)
-#define KEYRING_ITEM_ATTRIBUTE_NAME "e-source-uid"
-#define KEYRING_ITEM_DISPLAY_FORMAT "Evolution Data Source %s"
-
typedef struct _AsyncContext AsyncContext;
struct _EAuthenticationSessionPrivate {
PROP_SOURCE_UID
};
-static SecretSchema schema = {
- "org.gnome.Evolution.Data.Source",
- SECRET_SCHEMA_DONT_MATCH_NAME,
- {
- { KEYRING_ITEM_ATTRIBUTE_NAME,
- SECRET_SCHEMA_ATTRIBUTE_STRING },
- { NULL, 0 }
- }
-};
-
/* Forward Declarations */
static void authentication_session_msg
(EAuthenticationSession *session,
EAuthenticationSessionResult session_result;
ESourceAuthenticationResult auth_result;
ESourceRegistryServer *server;
- ESource *source;
+ ESource *source = NULL;
GcrPrompt *prompt;
GString *password_string;
- gboolean allow_auth_prompt;
const gchar *label;
const gchar *source_uid;
const gchar *prompt_password;
gchar *stored_password = NULL;
gboolean success;
+ gboolean allow_auth_prompt = TRUE;
gboolean remember_password = TRUE;
GError *local_error = NULL;
source_uid = e_authentication_session_get_source_uid (session);
authenticator = e_authentication_session_get_authenticator (session);
+ /* This will return NULL if the authenticating data source
+ * has not yet been submitted to the D-Bus registry service. */
+ source = e_source_registry_server_ref_source (server, source_uid);
+
if (e_source_authenticator_get_without_password (authenticator)) {
password_string = g_string_new ("");
/* if an empty password fails, then ask a user for it */
}
- success = e_authentication_session_lookup_password_sync (
- session, cancellable, &stored_password, error);
+ if (source != NULL) {
+ ESourceExtension *extension;
+ const gchar *extension_name;
- if (!success) {
- session_result = E_AUTHENTICATION_SESSION_ERROR;
- goto exit;
+ success = e_source_lookup_password_sync (
+ source, cancellable, &stored_password, error);
+
+ if (!success) {
+ session_result = E_AUTHENTICATION_SESSION_ERROR;
+ goto exit;
+ }
+
+ extension_name = E_SOURCE_EXTENSION_AUTHENTICATION;
+ extension = e_source_get_extension (source, extension_name);
+
+ allow_auth_prompt =
+ e_server_side_source_get_allow_auth_prompt (
+ E_SERVER_SIDE_SOURCE (source));
+
+ remember_password =
+ e_source_authentication_get_remember_password (
+ E_SOURCE_AUTHENTICATION (extension));
}
auth_result = E_SOURCE_AUTHENTICATION_REJECTED;
* Failure here does not affect the outcome of this operation,
* but leave a breadcrumb as evidence that something went wrong. */
- e_authentication_session_delete_password_sync (
- session, cancellable, &local_error);
-
- if (local_error != NULL) {
- g_warning ("%s: %s", G_STRFUNC, local_error->message);
- g_clear_error (&local_error);
- }
-
- /* This will return NULL if the authenticating data source
- * has not yet been submitted to the D-Bus registry service. */
- source = e_source_registry_server_ref_source (server, source_uid);
if (source != NULL) {
- ESourceExtension *extension;
- const gchar *extension_name;
+ e_source_delete_password_sync (
+ source, cancellable, &local_error);
- allow_auth_prompt =
- e_server_side_source_get_allow_auth_prompt (
- E_SERVER_SIDE_SOURCE (source));
-
- extension_name = E_SOURCE_EXTENSION_AUTHENTICATION;
- extension = e_source_get_extension (source, extension_name);
- remember_password =
- e_source_authentication_get_remember_password (
- E_SOURCE_AUTHENTICATION (extension));
-
- g_object_unref (source);
- } else {
- allow_auth_prompt = TRUE;
+ if (local_error != NULL) {
+ g_warning ("%s: %s", G_STRFUNC, local_error->message);
+ g_clear_error (&local_error);
+ }
}
/* Check if we're allowed to interrupt the user for a password.
goto close_prompt;
}
- source = e_source_registry_server_ref_source (server, source_uid);
if (source != NULL) {
ESourceExtension *extension;
const gchar *extension_name;
e_source_authentication_set_remember_password (
E_SOURCE_AUTHENTICATION (extension),
gcr_prompt_get_choice_chosen (prompt));
-
- g_object_unref (source);
}
/* Attempt authentication with the provided password. */
g_object_unref (prompt);
- e_authentication_session_store_password_sync (
- session, password_copy, permanently,
- cancellable, &local_error);
+ /* Create a phony "scratch" source if necessary. */
+ if (source == NULL) {
+ source = e_source_new_with_uid (
+ source_uid, NULL, &local_error);
+ }
+
+ if (source != NULL) {
+ e_source_store_password_sync (
+ source, password_copy, permanently,
+ cancellable, &local_error);
+ }
if (local_error != NULL) {
g_warning ("%s: %s", G_STRFUNC, local_error->message);
g_warn_if_reached ();
}
+ g_clear_object (&source);
+
return session_result;
}
* Returns: %TRUE on success, %FALSE on error
*
* Since: 3.6
+ *
+ * Deprecated: 3.12: Use e_source_store_password_sync() instead.
**/
gboolean
e_authentication_session_store_password_sync (EAuthenticationSession *session,
GCancellable *cancellable,
GError **error)
{
- gboolean result;
- const gchar *collection;
+ ESourceRegistryServer *server;
+ ESource *source;
const gchar *uid;
- gchar *display_name;
+ gboolean success = FALSE;
g_return_val_if_fail (E_IS_AUTHENTICATION_SESSION (session), FALSE);
- g_return_val_if_fail (password != NULL, FALSE);
-
- if (permanently)
- collection = SECRET_COLLECTION_DEFAULT;
- else
- collection = SECRET_COLLECTION_SESSION;
+ server = e_authentication_session_get_server (session);
uid = e_authentication_session_get_source_uid (session);
- display_name = g_strdup_printf (KEYRING_ITEM_DISPLAY_FORMAT, uid);
- result = secret_password_store_sync (
- &schema, collection, display_name,
- password, cancellable, error,
- KEYRING_ITEM_ATTRIBUTE_NAME, uid,
- NULL);
+ /* Try to use the registered ESource instance,
+ * otherwise create a phony "scratch" source. */
- g_free (display_name);
+ source = e_source_registry_server_ref_source (server, uid);
- return result;
+ if (source == NULL)
+ source = e_source_new_with_uid (uid, NULL, error);
+
+ if (source != NULL) {
+ success = e_source_store_password_sync (
+ source, password, permanently, cancellable, error);
+ g_object_unref (source);
+ }
+
+ return success;
}
/**
* of the operation.
*
* Since: 3.6
+ *
+ * Deprecated: 3.12: Use e_source_store_password() instead.
**/
void
e_authentication_session_store_password (EAuthenticationSession *session,
* Returns: %TRUE on success, %FALSE on error
*
* Since: 3.6
+ *
+ * Deprecated: 3.12: Use e_source_store_password_finish() instead.
**/
gboolean
e_authentication_session_store_password_finish (EAuthenticationSession *session,
* Returns: %TRUE on success, %FALSE on error
*
* Since: 3.6
+ *
+ * Deprecated: 3.12: Use e_source_lookup_password_sync() instead.
**/
gboolean
e_authentication_session_lookup_password_sync (EAuthenticationSession *session,
gchar **password,
GError **error)
{
+ ESourceRegistryServer *server;
+ ESource *source;
const gchar *uid;
- gchar *temp = NULL;
- gboolean success = TRUE;
- GError *local_error = NULL;
+ gboolean success = FALSE;
g_return_val_if_fail (E_IS_AUTHENTICATION_SESSION (session), FALSE);
+ server = e_authentication_session_get_server (session);
uid = e_authentication_session_get_source_uid (session);
- temp = secret_password_lookup_sync (
- &schema, cancellable, &local_error,
- KEYRING_ITEM_ATTRIBUTE_NAME, uid, NULL);
+ /* Try to use the registered ESource instance,
+ * otherwise create a phony "scratch" source. */
- if (local_error != NULL) {
- g_warn_if_fail (temp == NULL);
- g_propagate_error (error, local_error);
- success = FALSE;
- } else if (password != NULL) {
- *password = temp; /* takes ownership */
- } else {
- secret_password_free (temp);
+ source = e_source_registry_server_ref_source (server, uid);
+
+ if (source == NULL)
+ source = e_source_new_with_uid (uid, NULL, error);
+
+ if (source != NULL) {
+ success = e_source_lookup_password_sync (
+ source, cancellable, password, error);
+ g_object_unref (source);
}
return success;
* result of the operation.
*
* Since: 3.6
+ *
+ * Deprecated: 3.12: Use e_source_lookup_password() instead.
**/
void
e_authentication_session_lookup_password (EAuthenticationSession *session,
* Returns: %TRUE on success, %FALSE on error
*
* Since: 3.6
+ *
+ * Deprecated: 3.12: Use e_source_lookup_password_finish() instead.
**/
gboolean
e_authentication_session_lookup_password_finish (EAuthenticationSession *session,
* Returns: %TRUE on success, %FALSE on error
*
* Since: 3.6
+ *
+ * Deprecated: 3.12: Use e_source_delete_password_sync() instead.
**/
gboolean
e_authentication_session_delete_password_sync (EAuthenticationSession *session,
GCancellable *cancellable,
GError **error)
{
+ ESourceRegistryServer *server;
+ ESource *source;
const gchar *uid;
- gboolean success = TRUE;
- GError *local_error = NULL;
+ gboolean success = FALSE;
g_return_val_if_fail (E_IS_AUTHENTICATION_SESSION (session), FALSE);
+ server = e_authentication_session_get_server (session);
uid = e_authentication_session_get_source_uid (session);
- /* The return value indicates whether any passwords were removed,
- * not whether the operation completed successfully. So we have
- * check the GError directly. */
- secret_password_clear_sync (
- &schema, cancellable, &local_error,
- KEYRING_ITEM_ATTRIBUTE_NAME, uid, NULL);
+ /* Try to use the registered ESource instance,
+ * otherwise create a phony "scratch" source. */
- if (local_error != NULL) {
- g_propagate_error (error, local_error);
- success = FALSE;
+ source = e_source_registry_server_ref_source (server, uid);
+
+ if (source == NULL)
+ source = e_source_new_with_uid (uid, NULL, error);
+
+ if (source != NULL) {
+ success = e_source_delete_password_sync (
+ source, cancellable, error);
+ g_object_unref (source);
}
return success;
* of the operation.
*
* Since: 3.6
+ *
+ * Deprecated: 3.12: Use e_source_delete_password() instead.
**/
void
e_authentication_session_delete_password (EAuthenticationSession *session,
* Returns: %TRUE on success, %FALSE on error
*
* Since: 3.6
+ *
+ * Deprecated: 3.12: Use e_source_delete_password_finish() instead.
**/
gboolean
e_authentication_session_delete_password_finish (EAuthenticationSession *session,
#include <string.h>
#include <glib/gi18n-lib.h>
+#include <libsecret/secret.h>
+
/* Private D-Bus classes. */
#include <e-dbus-source.h>
#define PRIMARY_GROUP_NAME "Data Source"
+#define KEYRING_ITEM_ATTRIBUTE_NAME "e-source-uid"
+#define KEYRING_ITEM_DISPLAY_FORMAT "Evolution Data Source '%s'"
+
typedef struct _AsyncContext AsyncContext;
typedef struct _RemoveContext RemoveContext;
ESource *scratch_source;
gchar *access_token;
gint expires_in;
+ gchar *password;
+ gboolean permanently;
};
/* Used in e_source_remove_sync() */
LAST_SIGNAL
};
+static SecretSchema password_schema = {
+ "org.gnome.Evolution.Data.Source",
+ SECRET_SCHEMA_DONT_MATCH_NAME,
+ {
+ { KEYRING_ITEM_ATTRIBUTE_NAME,
+ SECRET_SCHEMA_ATTRIBUTE_STRING },
+ { NULL, 0 }
+ }
+};
+
static guint signals[LAST_SIGNAL];
/* Forward Declarations */
g_object_unref (async_context->scratch_source);
g_free (async_context->access_token);
+ g_free (async_context->password);
g_slice_free (AsyncContext, async_context);
}
source, result, out_access_token, out_expires_in, error);
}
+/**
+ * e_source_store_password_sync:
+ * @source: an #ESource
+ * @password: the password to store
+ * @permanently: store permanently or just for the session
+ * @cancellable: optional #GCancellable object, or %NULL
+ * @error: return location for a #GError, or %NULL
+ *
+ * Stores a password for @source. This operation does not rely on the
+ * registry service and therefore works for any #ESource -- registered
+ * or "scratch".
+ *
+ * If @permanently is %TRUE, the password is stored in the default keyring.
+ * Otherwise the password is stored in the memory-only session keyring. If
+ * an error occurs, the function sets @error and returns %FALSE.
+ *
+ * Returns: %TRUE on success, %FALSE on error
+ *
+ * Since: 3.12
+ **/
+gboolean
+e_source_store_password_sync (ESource *source,
+ const gchar *password,
+ gboolean permanently,
+ GCancellable *cancellable,
+ GError **error)
+{
+ gboolean success;
+ const gchar *collection;
+ const gchar *uid;
+ gchar *label;
+
+ g_return_val_if_fail (E_IS_SOURCE (source), FALSE);
+ g_return_val_if_fail (password != NULL, FALSE);
+
+ if (permanently)
+ collection = SECRET_COLLECTION_DEFAULT;
+ else
+ collection = SECRET_COLLECTION_SESSION;
+
+ uid = e_source_get_uid (source);
+ label = g_strdup_printf (KEYRING_ITEM_DISPLAY_FORMAT, uid);
+
+ success = secret_password_store_sync (
+ &password_schema,
+ collection, label, password,
+ cancellable, error,
+ KEYRING_ITEM_ATTRIBUTE_NAME, uid,
+ NULL);
+
+ g_free (label);
+
+ return success;
+}
+
+/* Helper for e_source_store_password() */
+static void
+source_store_password_thread (GTask *task,
+ gpointer source_object,
+ gpointer task_data,
+ GCancellable *cancellable)
+{
+ gboolean success;
+ AsyncContext *async_context;
+ GError *local_error = NULL;
+
+ async_context = (AsyncContext *) task_data;
+
+ success = e_source_store_password_sync (
+ E_SOURCE (source_object),
+ async_context->password,
+ async_context->permanently,
+ cancellable, &local_error);
+
+ if (local_error != NULL) {
+ g_task_return_error (task, local_error);
+ } else {
+ g_task_return_boolean (task, success);
+ }
+}
+
+/**
+ * e_source_store_password:
+ * @source: an #ESource
+ * @password: the password to store
+ * @permanently: store permanently or just for the session
+ * @cancellable: optional #GCancellable object, or %NULL
+ * @callback: a #GAsyncReadyCallback to call when the request is satisfied
+ * @user_data: data to pass to the callback function
+ *
+ * Asynchronously stores a password for @source. This operation does
+ * not rely on the registry service and therefore works for any #ESource
+ * -- registered or "scratch".
+ *
+ * If @permanently is %TRUE, the password is stored in the default keyring.
+ * Otherwise the password is stored in the memory-only session keyring. If
+ * an error occurs, the function sets @error and returns %FALSE.
+ *
+ * When the operation is finished, @callback will be called. You can then
+ * call e_source_store_password_finish() to get the result of the operation.
+ *
+ * Since: 3.12
+ **/
+void
+e_source_store_password (ESource *source,
+ const gchar *password,
+ gboolean permanently,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ GTask *task;
+ AsyncContext *async_context;
+
+ g_return_if_fail (E_IS_SOURCE (source));
+ g_return_if_fail (password != NULL);
+
+ async_context = g_slice_new0 (AsyncContext);
+ async_context->password = g_strdup (password);
+ async_context->permanently = permanently;
+
+ task = g_task_new (source, cancellable, callback, user_data);
+ g_task_set_source_tag (task, e_source_store_password);
+
+ g_task_set_task_data (
+ task, async_context,
+ (GDestroyNotify) async_context_free);
+
+ g_task_run_in_thread (task, source_store_password_thread);
+
+ g_object_unref (task);
+}
+
+/**
+ * e_source_store_password_finish:
+ * @source: an #ESource
+ * @result: a #GAsyncResult
+ * @error: return location for a #GError, or %NULL
+ *
+ * Finishes the operation started with e_source_store_password().
+ *
+ * Returns: %TRUE on success, %FALSE on error
+ *
+ * Since: 3.12
+ **/
+gboolean
+e_source_store_password_finish (ESource *source,
+ GAsyncResult *result,
+ GError **error)
+{
+ g_return_val_if_fail (E_IS_SOURCE (source), FALSE);
+ g_return_val_if_fail (g_task_is_valid (result, source), FALSE);
+
+ g_return_val_if_fail (
+ g_async_result_is_tagged (
+ result, e_source_store_password), FALSE);
+
+ return g_task_propagate_boolean (G_TASK (result), error);
+}
+
+/**
+ * e_source_lookup_password_sync:
+ * @source: an #ESource
+ * @cancellable: optional #GCancellable object, or %NULL
+ * @out_password: return location for the password, or %NULL
+ * @error: return location for a #GError, or %NULL
+ *
+ * Looks up a password for @source. Both the default and session keyrings
+ * are queried. This operation does not rely on the registry service and
+ * therefore works for any #ESource -- registered or "scratch".
+ *
+ * Note the boolean return value indicates whether the lookup operation
+ * itself completed successfully, not whether a password was found. If
+ * no password was found, the function will set @out_password to %NULL
+ * but still return %TRUE. If an error occurs, the function sets @error
+ * and returns %FALSE.
+ *
+ * Returns: %TRUE on success, %FALSE on error
+ *
+ * Since: 3.12
+ **/
+gboolean
+e_source_lookup_password_sync (ESource *source,
+ GCancellable *cancellable,
+ gchar **out_password,
+ GError **error)
+{
+ const gchar *uid;
+ gchar *temp = NULL;
+ gboolean success = TRUE;
+ GError *local_error = NULL;
+
+ g_return_val_if_fail (E_IS_SOURCE (source), FALSE);
+
+ uid = e_source_get_uid (source);
+
+ temp = secret_password_lookup_sync (
+ &password_schema,
+ cancellable, &local_error,
+ KEYRING_ITEM_ATTRIBUTE_NAME, uid,
+ NULL);
+
+ if (local_error != NULL) {
+ g_warn_if_fail (temp == NULL);
+ g_propagate_error (error, local_error);
+ success = FALSE;
+ } else if (out_password != NULL) {
+ *out_password = temp; /* takes ownership */
+ } else {
+ secret_password_free (temp);
+ }
+
+ return success;
+}
+
+/* Helper for e_source_lookup_password() */
+static void
+source_lookup_password_thread (GTask *task,
+ gpointer source_object,
+ gpointer task_data,
+ GCancellable *cancellable)
+{
+ gboolean success;
+ AsyncContext *async_context;
+ GError *local_error = NULL;
+
+ async_context = (AsyncContext *) task_data;
+
+ success = e_source_lookup_password_sync (
+ E_SOURCE (source_object),
+ cancellable,
+ &async_context->password,
+ &local_error);
+
+ if (local_error != NULL) {
+ g_task_return_error (task, local_error);
+ } else {
+ g_task_return_boolean (task, success);
+ }
+}
+
+/**
+ * e_source_lookup_password:
+ * @source: an #ESource
+ * @cancellable: optional #GCancellable object, or %NULL
+ * @callback: a #GAsyncReadyCallback to call when the request is satisfied
+ * @user_data: data to pass to the callback function
+ *
+ * Asynchronously looks up a password for @source. Both the default and
+ * session keyrings are queried. This operation does not rely on the
+ * registry service and therefore works for any #ESource -- registered
+ * or "scratch".
+ *
+ * When the operation is finished, @callback will be called. You can then
+ * call e_source_lookup_password_finish() to get the result of the operation.
+ *
+ * Since: 3.12
+ **/
+void
+e_source_lookup_password (ESource *source,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ GTask *task;
+ AsyncContext *async_context;
+
+ g_return_if_fail (E_IS_SOURCE (source));
+
+ async_context = g_slice_new0 (AsyncContext);
+
+ task = g_task_new (source, cancellable, callback, user_data);
+ g_task_set_source_tag (task, e_source_lookup_password);
+
+ g_task_set_task_data (
+ task, async_context,
+ (GDestroyNotify) async_context_free);
+
+ g_task_run_in_thread (task, source_lookup_password_thread);
+
+ g_object_unref (task);
+}
+
+/**
+ * e_source_lookup_password_finish:
+ * @source: an #ESource
+ * @result: a #GAsyncResult
+ * @out_password: return location for the password, or %NULL
+ * @error: return location for a #GError, or %NULL
+ *
+ * Finishes the operation started with e_source_lookup_password().
+ *
+ * Note the boolean return value indicates whether the lookup operation
+ * itself completed successfully, not whether a password was found. If
+ * no password was found, the function will set @out_password to %NULL
+ * but still return %TRUE. If an error occurs, the function sets @error
+ * and returns %FALSE.
+ *
+ * Returns: %TRUE on success, %FALSE on error
+ *
+ * Since: 3.12
+ **/
+gboolean
+e_source_lookup_password_finish (ESource *source,
+ GAsyncResult *result,
+ gchar **out_password,
+ GError **error)
+{
+ AsyncContext *async_context;
+
+ g_return_val_if_fail (E_IS_SOURCE (source), FALSE);
+ g_return_val_if_fail (g_task_is_valid (result, source), FALSE);
+
+ g_return_val_if_fail (
+ g_async_result_is_tagged (
+ result, e_source_lookup_password), FALSE);
+
+ async_context = g_task_get_task_data (G_TASK (result));
+
+ if (!g_task_had_error (G_TASK (result))) {
+ if (out_password != NULL) {
+ *out_password = async_context->password;
+ async_context->password = NULL;
+ }
+ }
+
+ return g_task_propagate_boolean (G_TASK (result), error);
+}
+
+/**
+ * e_source_delete_password_sync:
+ * @source: an #ESource
+ * @cancellable: optional #GCancellable object, or %NULL
+ * @error: return location for a #GError, or %NULL
+ *
+ * Deletes the password for @source from either the default keyring or
+ * session keyring. This operation does not rely on the registry service
+ * and therefore works for any #ESource -- registered or "scratch".
+ *
+ * Note the boolean return value indicates whether the delete operation
+ * itself completed successfully, not whether a password was found and
+ * deleted. If no password was found, the function will still return
+ * %TRUE. If an error occurs, the function sets @error and returns %FALSE.
+ *
+ * Returns: %TRUE on success, %FALSE on error
+ *
+ * Since: 3.12
+ **/
+gboolean
+e_source_delete_password_sync (ESource *source,
+ GCancellable *cancellable,
+ GError **error)
+{
+ const gchar *uid;
+ gboolean success = TRUE;
+ GError *local_error = NULL;
+
+ g_return_val_if_fail (E_IS_SOURCE (source), FALSE);
+
+ uid = e_source_get_uid (source);
+
+ /* The return value indicates whether any passwords were removed,
+ * not whether the operation completed successfully. So we have
+ * to check the GError directly. */
+ secret_password_clear_sync (
+ &password_schema,
+ cancellable, &local_error,
+ KEYRING_ITEM_ATTRIBUTE_NAME, uid,
+ NULL);
+
+ if (local_error != NULL) {
+ g_propagate_error (error, local_error);
+ success = FALSE;
+ }
+
+ return success;
+}
+
+/* Helper for e_source_delete_password() */
+static void
+source_delete_password_thread (GTask *task,
+ gpointer source_object,
+ gpointer task_data,
+ GCancellable *cancellable)
+{
+ gboolean success;
+ GError *local_error = NULL;
+
+ success = e_source_delete_password_sync (
+ E_SOURCE (source_object),
+ cancellable, &local_error);
+
+ if (local_error != NULL) {
+ g_task_return_error (task, local_error);
+ } else {
+ g_task_return_boolean (task, success);
+ }
+}
+
+/**
+ * e_source_delete_password:
+ * @source: an #ESource
+ * @cancellable: optional #GCancellable object, or %NULL
+ * @callback: a #GAsyncReadyCallback to call when the request is satisfied
+ * @user_data: data to pass to the callback function
+ *
+ * Asynchronously deletes the password for @source from either the default
+ * keyring or session keyring. This operation does not rely on the registry
+ * service and therefore works for any #ESource -- registered or "scratch".
+ *
+ * When the operation is finished, @callback will be called. You can then
+ * call e_source_delete_password_finish() to get the result of the operation.
+ *
+ * Since: 3.12
+ **/
+void
+e_source_delete_password (ESource *source,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ GTask *task;
+
+ g_return_if_fail (E_IS_SOURCE (source));
+
+ task = g_task_new (source, cancellable, callback, user_data);
+ g_task_set_source_tag (task, e_source_delete_password);
+
+ g_task_run_in_thread (task, source_delete_password_thread);
+
+ g_object_unref (task);
+}
+
+/**
+ * e_source_delete_password_finish:
+ * @source: an #ESource
+ * @result: a #GAsyncResult
+ * @error: return location for a #GError, or %NULL
+ *
+ * Finishes the operation started with e_source_delete_password().
+ *
+ * Note the boolean return value indicates whether the delete operation
+ * itself completed successfully, not whether a password was found and
+ * deleted. If no password was found, the function will still return
+ * %TRUE. If an error occurs, the function sets @error and returns %FALSE.
+ *
+ * Returns: %TRUE on success, %FALSE on error
+ *
+ * Since: 3.12
+ **/
+gboolean
+e_source_delete_password_finish (ESource *source,
+ GAsyncResult *result,
+ GError **error)
+{
+ g_return_val_if_fail (E_IS_SOURCE (source), FALSE);
+ g_return_val_if_fail (g_task_is_valid (result, source), FALSE);
+
+ g_return_val_if_fail (
+ g_async_result_is_tagged (
+ result, e_source_delete_password), FALSE);
+
+ return g_task_propagate_boolean (G_TASK (result), error);
+}
+