Add PurpleCredentialProvider as the first piece to replace the existing keyring api.
Testing Done:
Added some new unit tests and made sure they passs.
Reviewed at https://reviews.imfreedom.org/r/144/
--- a/doc/reference/libpurple/libpurple-docs.xml Thu Oct 08 23:31:08 2020 -0500
+++ b/doc/reference/libpurple/libpurple-docs.xml Thu Oct 08 23:37:43 2020 -0500
@@ -69,6 +69,7 @@
<xi:include href="xml/purpleaccountusersplit.xml" />
<xi:include href="xml/purplebuddypresence.xml" />
<xi:include href="xml/purplechatuser.xml" />
+ <xi:include href="xml/purplecredentialprovider.xml" /> <xi:include href="xml/purpleimconversation.xml" />
<xi:include href="xml/purplekeyvaluepair.xml" />
<xi:include href="xml/purpleprotocolfactory.xml" />
--- a/libpurple/meson.build Thu Oct 08 23:31:08 2020 -0500
+++ b/libpurple/meson.build Thu Oct 08 23:37:43 2020 -0500
@@ -51,10 +51,11 @@
'purpleaccountpresence.c',
'purpleaccountusersplit.c',
+ 'purplecredentialprovider.c', 'purpleimconversation.c',
'purpleprotocolfactory.c',
@@ -136,6 +137,7 @@
'purpleaccountusersplit.h',
+ 'purplecredentialprovider.h', 'purpleimconversation.h',
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/libpurple/purplecredentialprovider.c Thu Oct 08 23:37:43 2020 -0500
@@ -0,0 +1,388 @@
+ * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see <https://www.gnu.org/licenses/>. +#include "purplecredentialprovider.h" +} PurpleCredentialProviderPrivate; +static GParamSpec *properties[N_PROPERTIES] = {NULL, }; +G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE(PurpleCredentialProvider, + purple_credential_provider, G_TYPE_OBJECT) +/****************************************************************************** + *****************************************************************************/ +purple_credential_provider_set_id(PurpleCredentialProvider *provider, + PurpleCredentialProviderPrivate *priv = NULL; + priv = purple_credential_provider_get_instance_private(provider); + priv->id = g_strdup(id); + g_object_notify_by_pspec(G_OBJECT(provider), properties[PROP_ID]); +purple_credential_provider_set_name(PurpleCredentialProvider *provider, + PurpleCredentialProviderPrivate *priv = NULL; + priv = purple_credential_provider_get_instance_private(provider); + priv->name = g_strdup(name); + g_object_notify_by_pspec(G_OBJECT(provider), properties[PROP_NAME]); +/****************************************************************************** + * GObject Implementation + *****************************************************************************/ +purple_credential_provider_get_property(GObject *obj, guint param_id, + GValue *value, GParamSpec *pspec) + PurpleCredentialProvider *provider = PURPLE_CREDENTIAL_PROVIDER(obj); + g_value_set_string(value, + purple_credential_provider_get_id(provider)); + g_value_set_string(value, + purple_credential_provider_get_name(provider)); + G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, param_id, pspec); +purple_credential_provider_set_property(GObject *obj, guint param_id, + const GValue *value, GParamSpec *pspec) + PurpleCredentialProvider *provider = PURPLE_CREDENTIAL_PROVIDER(obj); + purple_credential_provider_set_id(provider, + g_value_get_string(value)); + purple_credential_provider_set_name(provider, + g_value_get_string(value)); + G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, param_id, pspec); +purple_credential_provider_finalize(GObject *obj) { + PurpleCredentialProvider *provider = NULL; + PurpleCredentialProviderPrivate *priv = NULL; + provider = PURPLE_CREDENTIAL_PROVIDER(obj); + priv = purple_credential_provider_get_instance_private(provider); + g_clear_pointer(&priv->id, g_free); + g_clear_pointer(&priv->name, g_free); + G_OBJECT_CLASS(purple_credential_provider_parent_class)->finalize(obj); +purple_credential_provider_init(PurpleCredentialProvider *provider) { +purple_credential_provider_class_init(PurpleCredentialProviderClass *klass) { + GObjectClass *obj_class = G_OBJECT_CLASS(klass); + obj_class->get_property = purple_credential_provider_get_property; + obj_class->set_property = purple_credential_provider_set_property; + obj_class->finalize = purple_credential_provider_finalize; + * PurpleCredentialProvider::id: + * The ID of the provider. Used for preferences and other things that need + properties[PROP_ID] = g_param_spec_string( + "id", "id", "The identifier of the provider", + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS + * PurpleCredentialProvider::name: + * The name of the provider which will be displayed to the user. + properties[PROP_NAME] = g_param_spec_string( + "name", "name", "The name of the provider", + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS + g_object_class_install_properties(obj_class, N_PROPERTIES, properties); +/****************************************************************************** + *****************************************************************************/ +purple_credential_provider_get_id(PurpleCredentialProvider *provider) { + PurpleCredentialProviderPrivate *priv = NULL; + g_return_val_if_fail(PURPLE_IS_CREDENTIAL_PROVIDER(provider), NULL); + priv = purple_credential_provider_get_instance_private(provider); +purple_credential_provider_get_name(PurpleCredentialProvider *provider) { + PurpleCredentialProviderPrivate *priv = NULL; + g_return_val_if_fail(PURPLE_IS_CREDENTIAL_PROVIDER(provider), NULL); + priv = purple_credential_provider_get_instance_private(provider); +purple_credential_provider_is_valid(PurpleCredentialProvider *provider, + PurpleCredentialProviderClass *klass = NULL; + g_return_val_if_fail(PURPLE_IS_CREDENTIAL_PROVIDER(provider), FALSE); + if(purple_credential_provider_get_id(provider) == NULL) { + g_set_error_literal(error, PURPLE_CREDENTIAL_PROVIDER_DOMAIN, 0, + if(purple_credential_provider_get_name(provider) == NULL) { + g_set_error_literal(error, PURPLE_CREDENTIAL_PROVIDER_DOMAIN, 1, + "provider has no name"); + klass = PURPLE_CREDENTIAL_PROVIDER_GET_CLASS(provider); + if(klass->read_password_async == NULL || klass->read_password_finish == NULL) { + g_set_error_literal(error, PURPLE_CREDENTIAL_PROVIDER_DOMAIN, 2, + "provider can not read passwords"); + if(klass->write_password_async == NULL || klass->write_password_finish == NULL) { + g_set_error_literal(error, PURPLE_CREDENTIAL_PROVIDER_DOMAIN, 3, + "provider can not write passwords"); +purple_credential_provider_read_password_async(PurpleCredentialProvider *provider, + PurpleAccount *account, + GCancellable *cancellable, + GAsyncReadyCallback callback, + PurpleCredentialProviderClass *klass = NULL; + g_return_if_fail(PURPLE_IS_CREDENTIAL_PROVIDER(provider)); + g_return_if_fail(PURPLE_IS_ACCOUNT(account)); + klass = PURPLE_CREDENTIAL_PROVIDER_GET_CLASS(provider); + if(klass && klass->read_password_async) { + klass->read_password_async(provider, account, cancellable, callback, +purple_credential_provider_read_password_finish(PurpleCredentialProvider *provider, + PurpleAccount *account, + PurpleCredentialProviderClass *klass = NULL; + g_return_val_if_fail(PURPLE_IS_CREDENTIAL_PROVIDER(provider), NULL); + g_return_val_if_fail(G_IS_ASYNC_RESULT(result), NULL); + klass = PURPLE_CREDENTIAL_PROVIDER_GET_CLASS(provider); + if(klass && klass->read_password_finish) { + return klass->read_password_finish(provider, account, result, error); +purple_credential_provider_write_password_async(PurpleCredentialProvider *provider, + PurpleAccount *account, + GCancellable *cancellable, + GAsyncReadyCallback callback, + PurpleCredentialProviderClass *klass = NULL; + g_return_if_fail(PURPLE_IS_CREDENTIAL_PROVIDER(provider)); + g_return_if_fail(PURPLE_IS_ACCOUNT(account)); + klass = PURPLE_CREDENTIAL_PROVIDER_GET_CLASS(provider); + if(klass && klass->write_password_async) { + klass->write_password_async(provider, account, password, cancellable, +purple_credential_provider_write_password_finish(PurpleCredentialProvider *provider, + PurpleAccount *account, + PurpleCredentialProviderClass *klass = NULL; + g_return_val_if_fail(PURPLE_IS_CREDENTIAL_PROVIDER(provider), FALSE); + g_return_val_if_fail(PURPLE_IS_ACCOUNT(account), FALSE); + g_return_val_if_fail(G_IS_ASYNC_RESULT(result), FALSE); + klass = PURPLE_CREDENTIAL_PROVIDER_GET_CLASS(provider); + if(klass && klass->write_password_finish) { + return klass->write_password_finish(provider, account, result, error); +purple_credential_provider_clear_password_async(PurpleCredentialProvider *provider, + PurpleAccount *account, + GCancellable *cancellable, + GAsyncReadyCallback callback, + PurpleCredentialProviderClass *klass = NULL; + g_return_if_fail(PURPLE_IS_CREDENTIAL_PROVIDER(provider)); + g_return_if_fail(PURPLE_IS_ACCOUNT(account)); + klass = PURPLE_CREDENTIAL_PROVIDER_GET_CLASS(provider); + if(klass && klass->clear_password_async) { + klass->clear_password_async(provider, account, cancellable, callback, +purple_credential_provider_clear_password_finish(PurpleCredentialProvider *provider, + PurpleAccount *account, + PurpleCredentialProviderClass *klass = NULL; + g_return_val_if_fail(PURPLE_IS_CREDENTIAL_PROVIDER(provider), FALSE); + g_return_val_if_fail(PURPLE_IS_ACCOUNT(account), FALSE); + g_return_val_if_fail(G_IS_ASYNC_RESULT(result), FALSE); + klass = PURPLE_CREDENTIAL_PROVIDER_GET_CLASS(provider); + if(klass && klass->clear_password_finish) { + return klass->clear_password_finish(provider, account, result, error); +purple_credential_provider_close(PurpleCredentialProvider *provider) { + PurpleCredentialProviderClass *klass = NULL; + g_return_if_fail(PURPLE_IS_CREDENTIAL_PROVIDER(provider)); + klass = PURPLE_CREDENTIAL_PROVIDER_GET_CLASS(provider); + if(klass && klass->close) { + klass->close(provider); +purple_credential_provider_read_settings(PurpleCredentialProvider *provider) { + PurpleCredentialProviderClass *klass = NULL; + g_return_val_if_fail(PURPLE_IS_CREDENTIAL_PROVIDER(provider), NULL); + klass = PURPLE_CREDENTIAL_PROVIDER_GET_CLASS(provider); + if(klass && klass->read_settings) { + return klass->read_settings(provider); +purple_credential_provider_write_settings(PurpleCredentialProvider *provider, + PurpleRequestFields *fields) + PurpleCredentialProviderClass *klass = NULL; + g_return_val_if_fail(PURPLE_IS_CREDENTIAL_PROVIDER(provider), FALSE); + g_return_val_if_fail(fields != NULL, FALSE); + klass = PURPLE_CREDENTIAL_PROVIDER_GET_CLASS(provider); + if(klass && klass->write_settings) { + return klass->write_settings(provider, fields); --- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/libpurple/purplecredentialprovider.h Thu Oct 08 23:37:43 2020 -0500
@@ -0,0 +1,278 @@
+ * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see <https://www.gnu.org/licenses/>. +#if !defined(PURPLE_GLOBAL_HEADER_INSIDE) && !defined(PURPLE_COMPILATION) +# error "only <purple.h> may be included directly" +#ifndef PURPLE_CREDENTIAL_PROVIDER_H +#define PURPLE_CREDENTIAL_PROVIDER_H +#include <glib-object.h> + * SECTION:purplecredentialprovider + * @section_id: libpurple-purplecredentialprovider + * @title: Credential Provider Object + * PURPLE_CREDENTIAL_PROVIDER_DOMAIN: + * A #GError domain for errors from #PurpleCredentialProviders. +#define PURPLE_CREDENTIAL_PROVIDER_DOMAIN (g_quark_from_static_string("purple-credential-provider")) + * PurpleCredentialProvider: + * #PurpleCredentialProvider is a base class that should be sub classed by + * credential providers. It defines the behavior of all credential providers + * and implements some shared properties. +#define PURPLE_TYPE_CREDENTIAL_PROVIDER (purple_credential_provider_get_type()) +G_DECLARE_DERIVABLE_TYPE(PurpleCredentialProvider, purple_credential_provider, + PURPLE, CREDENTIAL_PROVIDER, GObject); + * PurpleCredentialProviderClass: + * @read_password_async: Reads a password from the provider. + * @read_password_finish: Finishes reading a password. + * @write_password_async: Writes a password to the provider. + * @write_password_finish: Finishes writing a password. + * @clear_password_async: Clears a password from the provider. + * @clear_password_finish: Finishes clearing a password from the provider. + * @close: Closes the provider. + * @read_settings: Creates a #PurpleRequestFields for the available settings. + * @write_settings: Updates the settings for provider. + * #PurpleCredentialProviderClass defines the interface for interacting with + * credential providers like libsecret, kwallet, etc. +struct _PurpleCredentialProviderClass { + void (*read_password_async)(PurpleCredentialProvider *provider, PurpleAccount *account, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer data); + gchar *(*read_password_finish)(PurpleCredentialProvider *provider, PurpleAccount *account, GAsyncResult *result, GError **error); + void (*write_password_async)(PurpleCredentialProvider *provider, PurpleAccount *account, const gchar *password, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer data); + gboolean (*write_password_finish)(PurpleCredentialProvider *provider, PurpleAccount *account, GAsyncResult *result, GError **error); + void (*clear_password_async)(PurpleCredentialProvider *provider, PurpleAccount *account, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer data); + gboolean (*clear_password_finish)(PurpleCredentialProvider *provider, PurpleAccount *account, GAsyncResult *result, GError **error); + void (*close)(PurpleCredentialProvider *provider); + PurpleRequestFields *(*read_settings)(PurpleCredentialProvider *provider); + gboolean (*write_settings)(PurpleCredentialProvider *provider, PurpleRequestFields *fields); + /* Some extra padding to play it safe. */ + * purple_credential_provider_get_id: + * @provider: The #PurpleCredentialProvider instance. + * Gets the identifier of @provider. + * Returns: The identifier of @provider. +const gchar *purple_credential_provider_get_id(PurpleCredentialProvider *provider); + * purple_credential_provider_get_name: + * @provider: The #PurpleCredentialProvider instance. + * Gets the name of @provider which can be show in user interfaces. + * Returns: The name of @provider. +const gchar *purple_credential_provider_get_name(PurpleCredentialProvider *provider); + * purple_credential_provider_is_valid: + * @provider: The #PurpleCredentialProvider instance. + * @error: (out) (optional): A return address for a #GError. + * Checks whether or not @provider is setup correctly. This is primarily meant + * for #purple_keyring_register to call to avoid programming errors, but can be + * Returns: %FALSE on error, otherwise %TRUE. +gboolean purple_credential_provider_is_valid(PurpleCredentialProvider *provider, GError **error); + * purple_credential_provider_read_password_async: + * @provider: The #PurpleCredentialProvider instance. + * @account: The #PurpleAccount whose password to read. + * @cancellable: (nullable): optional GCancellable object, NULL to ignore. + * @callback: (scope async): a GAsyncReadyCallback to call when the request is satisfied. + * @data: User data to pass to @callback. + * Reads the password for @account from @provider. +void purple_credential_provider_read_password_async(PurpleCredentialProvider *provider, PurpleAccount *account, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer data); + * purple_credential_provider_read_password_finish: + * @provider: The #PurpleCredentialProvider instance. + * @account: The #PurpleAccount whose password we're looking up. + * @result: The #GAsyncResult from the previous + * purple_credential_provider_read_password() call. + * @error: (out) (optional): Return address for a #GError. + * Finishes a previous call to purple_credential_provider_read_password(). + * Returns: (transfer full): The password or %NULL if successful, otherwise + * %NULL with @error set on failure. +gchar *purple_credential_provider_read_password_finish(PurpleCredentialProvider *provider, PurpleAccount *account, GAsyncResult *result, GError **error); + * purple_credential_provider_write_password_async: + * @provider: The #PurpleCredentialProvider instance. + * @account: The #PurpleAccount whose password to write. + * @password: The password to write. + * @cancellable: (nullable): optional GCancellable object, NULL to ignore. + * @callback: (scope async): a #GAsyncReadyCallback to call when the request is + * @data: User data to pass to @callback. + * Writes @password for @account to @provider. +void purple_credential_provider_write_password_async(PurpleCredentialProvider *provider, PurpleAccount *account, const gchar *password, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer data); + * purple_credential_provider_write_password_finish: + * @provider: The #PurpleCredentialProvider instance. + * @account: The #PurpleAccount whose password we're writing. + * @result: The #GAsyncResult from the previous + * purple_credential_provider_write_password() call. + * @error: (out) (optional): Return address for a #GError. + * Finishes a previous call to purple_credential_provider_write_password(). + * Returns: %TRUE if the password was written successfully, otherwise %FALSE +gboolean purple_credential_provider_write_password_finish(PurpleCredentialProvider *provider, PurpleAccount *account, GAsyncResult *result, GError **error); + * purple_credential_provider_clear_password_async: + * @provider: The #PurpleCredentialProvider instance. + * @account: The #PurpleAccount whose password to clear. + * @cancellable: (nullable): optional #GCancellable object, or %NULL to ignore. + * @callback: (scope async): a #GAsyncReadyCallback to call when the request is + * @data: User data to pass to @callback. + * Clears the password for @account from @provider. +void purple_credential_provider_clear_password_async(PurpleCredentialProvider *provider, PurpleAccount *account, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer data); + * purple_credential_provider_clear_password_finish: + * @provider: The #PurpleCredentialProvider instance. + * @account: The #PurpleAccount whose password we're clearing. + * @result: The #GAsyncResult from the previous + * purple_credential_provider_clear_password() call. + * @error: (out) (optional): Return address for a #GError. + * Finishes a previous call to purple_credential_provider_clear_password(). + * Returns: %TRUE if the password was cleared successfully, otherwise %FALSE +gboolean purple_credential_provider_clear_password_finish(PurpleCredentialProvider *provider, PurpleAccount *account, GAsyncResult *result, GError **error); + * purple_credential_provider_close: + * @provider: The #PurpleCredentialProvider instance. + * Tells @provider to close. This is useful if you need to disconnect a socket + * or close a file to save memory. +void purple_credential_provider_close(PurpleCredentialProvider *provider); + * purple_credential_provider_read_settings: + * @provider: The #PurpleCredentialProviderInstance. + * Reads settings from @provider. + * Returns: (transfer full): New copy of current settings which must be free'd + * with purple_request_fields_destroy(). +PurpleRequestFields *purple_credential_provider_read_settings(PurpleCredentialProvider *provider); + * purple_credential_provider_write_settings: + * @provider: The #PurpleCredentialProvider instance. + * @fields: Modified settings from purple_credential_provider_read_settings(). + * Write @fields to @provider. + * Returns: %TRUE if successful, %FALSE otherwise. +gboolean purple_credential_provider_write_settings(PurpleCredentialProvider *provider, PurpleRequestFields *fields); +#endif /* PURPLE_CREDENTIAL_PROVIDER */ --- a/libpurple/tests/meson.build Thu Oct 08 23:31:08 2020 -0500
+++ b/libpurple/tests/meson.build Thu Oct 08 23:37:43 2020 -0500
@@ -2,6 +2,7 @@
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/libpurple/tests/test_credential_provider.c Thu Oct 08 23:37:43 2020 -0500
@@ -0,0 +1,656 @@
+ * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see <https://www.gnu.org/licenses/>. +/****************************************************************************** + *****************************************************************************/ +/* Since we're using GTask to test asynchrous functions, we need to use a main +static GMainLoop *loop = FALSE; +/****************************************************************************** + * TestCredentialProviderEmpty + *****************************************************************************/ +#define TEST_PURPLE_TYPE_CREDENTIAL_PROVIDER_EMPTY (test_purple_credential_provider_empty_get_type()) +G_DECLARE_FINAL_TYPE(TestPurpleCredentialProviderEmpty, + test_purple_credential_provider_empty, + TEST_PURPLE, CREDENTIAL_PROVIDER_EMPTY, + PurpleCredentialProvider) +struct _TestPurpleCredentialProviderEmpty { + PurpleCredentialProvider parent; +G_DEFINE_TYPE(TestPurpleCredentialProviderEmpty, + test_purple_credential_provider_empty, + PURPLE_TYPE_CREDENTIAL_PROVIDER) +test_purple_credential_provider_empty_read_password_async(PurpleCredentialProvider *provider, + PurpleAccount *account, + GCancellable *cancellable, + GAsyncReadyCallback callback, +test_purple_credential_provider_empty_read_password_finish(PurpleCredentialProvider *provider, + PurpleAccount *account, +test_purple_credential_provider_empty_write_password_async(PurpleCredentialProvider *provider, + PurpleAccount *account, + GCancellable *cancellable, + GAsyncReadyCallback callback, +test_purple_credential_provider_empty_write_password_finish(PurpleCredentialProvider *provider, + PurpleAccount *account, +test_purple_credential_provider_empty_class_init(TestPurpleCredentialProviderEmptyClass *klass) +test_purple_credential_provider_empty_init(TestPurpleCredentialProviderEmpty *provider) +/****************************************************************************** + * purple_credential_provider_is_valid tests + *****************************************************************************/ +test_purple_credential_provider_is_valid_no_id(void) { + PurpleCredentialProvider *provider = NULL; + provider = g_object_new( + TEST_PURPLE_TYPE_CREDENTIAL_PROVIDER_EMPTY, + g_assert_false(purple_credential_provider_is_valid(provider, &error)); + g_assert_error(error, PURPLE_CREDENTIAL_PROVIDER_DOMAIN, 0); + g_object_unref(G_OBJECT(provider)); +test_purple_credential_provider_is_valid_no_name(void) { + PurpleCredentialProvider *provider = NULL; + provider = g_object_new( + TEST_PURPLE_TYPE_CREDENTIAL_PROVIDER_EMPTY, + g_assert_false(purple_credential_provider_is_valid(provider, &error)); + g_assert_error(error, PURPLE_CREDENTIAL_PROVIDER_DOMAIN, 1); + g_object_unref(G_OBJECT(provider)); +test_purple_credential_provider_is_valid_no_reader(void) { + PurpleCredentialProvider *provider = NULL; + PurpleCredentialProviderClass *klass = NULL; + provider = g_object_new( + TEST_PURPLE_TYPE_CREDENTIAL_PROVIDER_EMPTY, + klass = PURPLE_CREDENTIAL_PROVIDER_GET_CLASS(provider); + klass->read_password_async = NULL; + klass->read_password_finish = NULL; + klass->write_password_async = test_purple_credential_provider_empty_write_password_async; + klass->write_password_finish = test_purple_credential_provider_empty_write_password_finish; + g_assert_false(purple_credential_provider_is_valid(provider, &error)); + g_assert_error(error, PURPLE_CREDENTIAL_PROVIDER_DOMAIN, 2); + g_object_unref(G_OBJECT(provider)); +test_purple_credential_provider_is_valid_no_writer(void) { + PurpleCredentialProvider *provider = NULL; + PurpleCredentialProviderClass *klass = NULL; + provider = g_object_new( + TEST_PURPLE_TYPE_CREDENTIAL_PROVIDER_EMPTY, + klass = PURPLE_CREDENTIAL_PROVIDER_GET_CLASS(provider); + klass->read_password_async = test_purple_credential_provider_empty_read_password_async; + klass->read_password_finish = test_purple_credential_provider_empty_read_password_finish; + klass->write_password_async = NULL; + klass->write_password_finish = NULL; + g_assert_false(purple_credential_provider_is_valid(provider, &error)); + g_assert_error(error, PURPLE_CREDENTIAL_PROVIDER_DOMAIN, 3); + g_object_unref(G_OBJECT(provider)); +test_purple_credential_provider_is_valid_valid(void) { + PurpleCredentialProvider *provider = NULL; + PurpleCredentialProviderClass *klass = NULL; + provider = g_object_new( + TEST_PURPLE_TYPE_CREDENTIAL_PROVIDER_EMPTY, + klass = PURPLE_CREDENTIAL_PROVIDER_GET_CLASS(provider); + klass->read_password_async = test_purple_credential_provider_empty_read_password_async; + klass->read_password_finish = test_purple_credential_provider_empty_read_password_finish; + klass->write_password_async = test_purple_credential_provider_empty_write_password_async; + klass->write_password_finish = test_purple_credential_provider_empty_write_password_finish; + g_assert_true(purple_credential_provider_is_valid(provider, &error)); + g_assert_no_error(error); + g_object_unref(G_OBJECT(provider)); +/****************************************************************************** + * TestPurpleCredentialProvider + *****************************************************************************/ +#define TEST_PURPLE_TYPE_CREDENTIAL_PROVIDER (test_purple_credential_provider_get_type()) +G_DECLARE_FINAL_TYPE(TestPurpleCredentialProvider, + test_purple_credential_provider, + TEST_PURPLE, CREDENTIAL_PROVIDER, + PurpleCredentialProvider) +struct _TestPurpleCredentialProvider { + PurpleCredentialProvider parent; + gboolean read_password_async; + gboolean read_password_finish; + gboolean write_password_async; + gboolean write_password_finish; + gboolean clear_password_async; + gboolean clear_password_finish; + gboolean read_settings; + gboolean write_settings; +G_DEFINE_TYPE(TestPurpleCredentialProvider, + test_purple_credential_provider, + PURPLE_TYPE_CREDENTIAL_PROVIDER) +test_purple_credential_provider_read_password_async(PurpleCredentialProvider *p, + PurpleAccount *account, + GCancellable *cancellable, + GAsyncReadyCallback callback, + TestPurpleCredentialProvider *provider = TEST_PURPLE_CREDENTIAL_PROVIDER(p); + provider->read_password_async = TRUE; + task = g_task_new(p, cancellable, callback, data); + g_task_return_pointer(task, NULL, NULL); + g_object_unref(G_OBJECT(task)); +test_purple_credential_provider_read_password_finish(PurpleCredentialProvider *p, + PurpleAccount *account, + TestPurpleCredentialProvider *provider = TEST_PURPLE_CREDENTIAL_PROVIDER(p); + provider->read_password_finish = TRUE; +test_purple_credential_provider_write_password_async(PurpleCredentialProvider *p, + PurpleAccount *account, + GCancellable *cancellable, + GAsyncReadyCallback callback, + TestPurpleCredentialProvider *provider = TEST_PURPLE_CREDENTIAL_PROVIDER(p); + provider->write_password_async = TRUE; + task = g_task_new(p, cancellable, callback, data); + g_task_return_boolean(task, TRUE); + g_object_unref(G_OBJECT(task)); +test_purple_credential_provider_write_password_finish(PurpleCredentialProvider *p, + PurpleAccount *account, + TestPurpleCredentialProvider *provider = TEST_PURPLE_CREDENTIAL_PROVIDER(p); + provider->write_password_finish = TRUE; +test_purple_credential_provider_clear_password_async(PurpleCredentialProvider *p, + PurpleAccount *account, + GCancellable *cancellable, + GAsyncReadyCallback callback, + TestPurpleCredentialProvider *provider = TEST_PURPLE_CREDENTIAL_PROVIDER(p); + provider->clear_password_async = TRUE; + task = g_task_new(p, cancellable, callback, data); + g_task_return_boolean(task, TRUE); + g_object_unref(G_OBJECT(task)); +test_purple_credential_provider_clear_password_finish(PurpleCredentialProvider *p, + PurpleAccount *account, + TestPurpleCredentialProvider *provider = TEST_PURPLE_CREDENTIAL_PROVIDER(p); + provider->clear_password_finish = TRUE; +test_purple_credential_provider_close(PurpleCredentialProvider *p) { + TestPurpleCredentialProvider *provider = TEST_PURPLE_CREDENTIAL_PROVIDER(p); + provider->close = TRUE; +static PurpleRequestFields * +test_purple_credential_provider_read_settings(PurpleCredentialProvider *p) { + TestPurpleCredentialProvider *provider = TEST_PURPLE_CREDENTIAL_PROVIDER(p); + provider->read_settings = TRUE; +test_purple_credential_provider_write_settings(PurpleCredentialProvider *p, + PurpleRequestFields *fields) + TestPurpleCredentialProvider *provider = TEST_PURPLE_CREDENTIAL_PROVIDER(p); + provider->write_settings = TRUE; +test_purple_credential_provider_init(TestPurpleCredentialProvider *provider) { +test_purple_credential_provider_class_init(TestPurpleCredentialProviderClass *klass) + PurpleCredentialProviderClass *provider_class = PURPLE_CREDENTIAL_PROVIDER_CLASS(klass); + provider_class->read_password_async = test_purple_credential_provider_read_password_async; + provider_class->read_password_finish = test_purple_credential_provider_read_password_finish; + provider_class->write_password_async = test_purple_credential_provider_write_password_async; + provider_class->write_password_finish = test_purple_credential_provider_write_password_finish; + provider_class->clear_password_async = test_purple_credential_provider_clear_password_async; + provider_class->clear_password_finish = test_purple_credential_provider_clear_password_finish; + provider_class->close = test_purple_credential_provider_close; + provider_class->read_settings = test_purple_credential_provider_read_settings; + provider_class->write_settings = test_purple_credential_provider_write_settings; +static PurpleCredentialProvider * +test_purple_credential_provider_new(void) { + TEST_PURPLE_TYPE_CREDENTIAL_PROVIDER, + "name", "Test Provider", +/****************************************************************************** + * TestPurpleCredentialProvider Tests + *****************************************************************************/ +test_purple_credential_provider_timeout_cb(gpointer data) { + g_main_loop_quit((GMainLoop *)data); + g_warning("timed out waiting for the callback function to be called"); +test_purple_credential_provider_test_read_cb(GObject *obj, GAsyncResult *res, + PurpleCredentialProvider *provider = PURPLE_CREDENTIAL_PROVIDER(obj); + PurpleAccount *account = PURPLE_ACCOUNT(d); + gchar *password = NULL; + password = purple_credential_provider_read_password_finish(provider, + g_object_unref(G_OBJECT(account)); + g_main_loop_quit(loop); + g_assert_null(password); +test_purple_credential_provider_test_read_idle(gpointer data) { + PurpleCredentialProvider *p = PURPLE_CREDENTIAL_PROVIDER(data); + PurpleAccount *account = NULL; + account = purple_account_new("test", "test"); + purple_credential_provider_read_password_async(p, account, NULL, + test_purple_credential_provider_test_read_cb, +test_purple_credential_provider_test_read(void) { + PurpleCredentialProvider *p = test_purple_credential_provider_new(); + TestPurpleCredentialProvider *tp = TEST_PURPLE_CREDENTIAL_PROVIDER(p); + g_idle_add(test_purple_credential_provider_test_read_idle, p); + g_timeout_add_seconds(10, test_purple_credential_provider_timeout_cb, loop); + g_assert_true(tp->read_password_async); + g_assert_true(tp->read_password_finish); + g_assert_false(tp->write_password_async); + g_assert_false(tp->write_password_finish); + g_assert_false(tp->clear_password_async); + g_assert_false(tp->clear_password_finish); + g_assert_false(tp->close); + g_assert_false(tp->read_settings); + g_assert_false(tp->write_settings); +test_purple_credential_provider_test_write_cb(GObject *obj, GAsyncResult *res, + PurpleCredentialProvider *provider = PURPLE_CREDENTIAL_PROVIDER(obj); + PurpleAccount *account = PURPLE_ACCOUNT(d); + test_purple_credential_provider_write_password_finish(provider, account, + g_object_unref(G_OBJECT(account)); + g_main_loop_quit(loop); +test_purple_credential_provider_test_write_idle(gpointer data) { + PurpleCredentialProvider *p = PURPLE_CREDENTIAL_PROVIDER(data); + PurpleAccount *account = NULL; + account = purple_account_new("test", "test"); + purple_credential_provider_write_password_async(p, account, NULL, NULL, + test_purple_credential_provider_test_write_cb, +test_purple_credential_provider_test_write(void) { + PurpleCredentialProvider *p = test_purple_credential_provider_new(); + TestPurpleCredentialProvider *tp = TEST_PURPLE_CREDENTIAL_PROVIDER(p); + g_idle_add(test_purple_credential_provider_test_write_idle, p); + g_timeout_add_seconds(10, test_purple_credential_provider_timeout_cb, loop); + g_assert_false(tp->read_password_async); + g_assert_false(tp->read_password_finish); + g_assert_true(tp->write_password_async); + g_assert_true(tp->write_password_finish); + g_assert_false(tp->clear_password_async); + g_assert_false(tp->clear_password_finish); + g_assert_false(tp->close); + g_assert_false(tp->read_settings); + g_assert_false(tp->write_settings); + g_object_unref(G_OBJECT(p)); +test_purple_credential_provider_test_clear_cb(GObject *obj, GAsyncResult *res, + PurpleCredentialProvider *provider = PURPLE_CREDENTIAL_PROVIDER(obj); + PurpleAccount *account = PURPLE_ACCOUNT(d); + test_purple_credential_provider_clear_password_finish(provider, account, + g_object_unref(G_OBJECT(account)); + g_main_loop_quit(loop); +test_purple_credential_provider_test_clear_idle(gpointer data) { + PurpleCredentialProvider *p = PURPLE_CREDENTIAL_PROVIDER(data); + PurpleAccount *account = NULL; + account = purple_account_new("test", "test"); + purple_credential_provider_clear_password_async(p, account, NULL, + test_purple_credential_provider_test_clear_cb, +test_purple_credential_provider_test_clear(void) { + PurpleCredentialProvider *p = test_purple_credential_provider_new(); + TestPurpleCredentialProvider *tp = TEST_PURPLE_CREDENTIAL_PROVIDER(p); + g_idle_add(test_purple_credential_provider_test_clear_idle, p); + g_timeout_add_seconds(10, test_purple_credential_provider_timeout_cb, loop); + g_assert_false(tp->read_password_async); + g_assert_false(tp->read_password_finish); + g_assert_false(tp->write_password_async); + g_assert_false(tp->write_password_finish); + g_assert_true(tp->clear_password_async); + g_assert_true(tp->clear_password_finish); + g_assert_false(tp->close); + g_assert_false(tp->read_settings); + g_assert_false(tp->write_settings); +test_purple_credential_provider_test_close(void) { + PurpleCredentialProvider *p = test_purple_credential_provider_new(); + TestPurpleCredentialProvider *tp = TEST_PURPLE_CREDENTIAL_PROVIDER(p); + purple_credential_provider_close(p); + g_assert_false(tp->read_password_async); + g_assert_false(tp->read_password_finish); + g_assert_false(tp->write_password_async); + g_assert_false(tp->write_password_finish); + g_assert_false(tp->clear_password_async); + g_assert_false(tp->clear_password_finish); + g_assert_true(tp->close); + g_assert_false(tp->read_settings); + g_assert_false(tp->write_settings); + g_object_unref(G_OBJECT(p)); +test_purple_credential_provider_test_read_settings(void) { + PurpleCredentialProvider *p = test_purple_credential_provider_new(); + TestPurpleCredentialProvider *tp = TEST_PURPLE_CREDENTIAL_PROVIDER(p); + purple_credential_provider_read_settings(p); + g_assert_false(tp->read_password_async); + g_assert_false(tp->read_password_finish); + g_assert_false(tp->write_password_async); + g_assert_false(tp->write_password_finish); + g_assert_false(tp->clear_password_async); + g_assert_false(tp->clear_password_finish); + g_assert_false(tp->close); + g_assert_true(tp->read_settings); + g_assert_false(tp->write_settings); + g_object_unref(G_OBJECT(p)); +test_purple_credential_provider_test_write_settings(void) { + PurpleCredentialProvider *p = test_purple_credential_provider_new(); + TestPurpleCredentialProvider *tp = TEST_PURPLE_CREDENTIAL_PROVIDER(p); + PurpleRequestFields *fields = purple_request_fields_new(); + purple_credential_provider_write_settings(p, fields); + purple_request_fields_destroy(fields); + g_assert_false(tp->read_password_async); + g_assert_false(tp->read_password_finish); + g_assert_false(tp->write_password_async); + g_assert_false(tp->write_password_finish); + g_assert_false(tp->clear_password_async); + g_assert_false(tp->clear_password_finish); + g_assert_false(tp->close); + g_assert_false(tp->read_settings); + g_assert_true(tp->write_settings); + g_object_unref(G_OBJECT(p)); +/****************************************************************************** + *****************************************************************************/ +main(gint argc, gchar *argv[]) { + g_test_init(&argc, &argv, NULL); + loop = g_main_loop_new(NULL, FALSE); + g_test_add_func("/credential-provider/is-valid/no-id", + test_purple_credential_provider_is_valid_no_id); + g_test_add_func("/credential-provider/is-valid/no-name", + test_purple_credential_provider_is_valid_no_name); + g_test_add_func("/credential-provider/is-valid/no-reader", + test_purple_credential_provider_is_valid_no_reader); + g_test_add_func("/credential-provider/is-valid/no-writer", + test_purple_credential_provider_is_valid_no_writer); + g_test_add_func("/credential-provider/is-valid/valid", + test_purple_credential_provider_is_valid_valid); + g_test_add_func("/credential-provider/functional/read", + test_purple_credential_provider_test_read); + g_test_add_func("/credential-provider/functional/write", + test_purple_credential_provider_test_write); + g_test_add_func("/credential-provider/functional/clear", + test_purple_credential_provider_test_clear); + g_test_add_func("/credential-provider/functional/close", + test_purple_credential_provider_test_close); + g_test_add_func("/credential-provider/functional/read_settings", + test_purple_credential_provider_test_read_settings); + g_test_add_func("/credential-provider/functional/write_settings", + test_purple_credential_provider_test_write_settings); + g_main_loop_unref(loop); --- a/po/POTFILES.in Thu Oct 08 23:31:08 2020 -0500
+++ b/po/POTFILES.in Thu Oct 08 23:37:43 2020 -0500
@@ -270,6 +270,7 @@
libpurple/purpleattachment.c
libpurple/purplebuddypresence.c
libpurple/purplechatuser.c
+libpurple/purplecredentialprovider.c libpurple/purpleimconversation.c
libpurple/purpleprotocolim.c
libpurple/purpleprotocolmedia.c