g_return_val_if_fail (source != NULL, NULL);
g_return_val_if_fail (E_IS_SOURCE (source), NULL);
+ LOCK_FACTORY ();
if (!gdbus_book_factory_activate (&err)) {
+ UNLOCK_FACTORY ();
if (err) {
unwrap_dbus_error (err, &err);
g_warning ("%s: Failed to run book factory: %s", G_STRFUNC, err->message);
xml = e_source_to_standalone_xml (source);
if (!xml || !*xml) {
+ UNLOCK_FACTORY ();
g_free (xml);
g_set_error_literal (error, E_CLIENT_ERROR, E_CLIENT_ERROR_INVALID_ARG, _("Invalid source"));
return NULL;
}
client = g_object_new (E_TYPE_BOOK_CLIENT, "source", source, NULL);
+ UNLOCK_FACTORY ();
if (!e_gdbus_book_factory_call_get_book_sync (G_DBUS_PROXY (book_factory_proxy), e_util_ensure_gdbus_string (xml, &gdbus_xml), &path, NULL, &err)) {
unwrap_dbus_error (err, &err);
}
}
-static gchar *
-book_client_retrieve_capabilities (EClient *client)
+static void
+book_client_retrieve_capabilities (EClient *client, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data)
{
EBookClient *book_client;
- GError *error = NULL;
- gchar *capabilities = NULL;
- g_return_val_if_fail (client != NULL, NULL);
+ g_return_if_fail (client != NULL);
book_client = E_BOOK_CLIENT (client);
- g_return_val_if_fail (book_client != NULL, NULL);
- g_return_val_if_fail (book_client->priv != NULL, NULL);
+ g_return_if_fail (book_client != NULL);
+ g_return_if_fail (book_client->priv != NULL);
- if (!book_client->priv->gdbus_book)
- return NULL;
+ book_client_get_backend_property (client, CLIENT_BACKEND_PROPERTY_CAPABILITIES, cancellable, callback, user_data);
+}
- e_gdbus_book_call_get_backend_property_sync (book_client->priv->gdbus_book, CLIENT_BACKEND_PROPERTY_CAPABILITIES, &capabilities, NULL, &error);
+static gboolean
+book_client_retrieve_capabilities_finish (EClient *client, GAsyncResult *result, gchar **capabilities, GError **error)
+{
+ EBookClient *book_client;
- if (error) {
- g_debug ("%s: Failed to retrieve capabilitites: %s", G_STRFUNC, error->message);
- g_error_free (error);
- }
+ g_return_val_if_fail (client != NULL, FALSE);
+
+ book_client = E_BOOK_CLIENT (client);
+ g_return_val_if_fail (book_client != NULL, FALSE);
+ g_return_val_if_fail (book_client->priv != NULL, FALSE);
+
+ return book_client_get_backend_property_finish (client, result, capabilities, error);
+}
+
+static gboolean
+book_client_retrieve_capabilities_sync (EClient *client, gchar **capabilities, GCancellable *cancellable, GError **error)
+{
+ EBookClient *book_client;
+
+ g_return_val_if_fail (client != NULL, FALSE);
+
+ book_client = E_BOOK_CLIENT (client);
+ g_return_val_if_fail (book_client != NULL, FALSE);
+ g_return_val_if_fail (book_client->priv != NULL, FALSE);
- return capabilities;
+ return book_client_get_backend_property_sync (client, CLIENT_BACKEND_PROPERTY_CAPABILITIES, capabilities, cancellable, error);
}
static void
client_class->unwrap_dbus_error = book_client_unwrap_dbus_error;
client_class->handle_authentication = book_client_handle_authentication;
client_class->retrieve_capabilities = book_client_retrieve_capabilities;
+ client_class->retrieve_capabilities_finish = book_client_retrieve_capabilities_finish;
+ client_class->retrieve_capabilities_sync = book_client_retrieve_capabilities_sync;
client_class->get_backend_property = book_client_get_backend_property;
client_class->get_backend_property_finish = book_client_get_backend_property_finish;
client_class->get_backend_property_sync = book_client_get_backend_property_sync;
g_return_val_if_fail (E_IS_SOURCE (source), NULL);
g_return_val_if_fail (source_type == E_CAL_CLIENT_SOURCE_TYPE_EVENTS || source_type == E_CAL_CLIENT_SOURCE_TYPE_TASKS || source_type == E_CAL_CLIENT_SOURCE_TYPE_MEMOS, NULL);
+ LOCK_FACTORY ();
if (!gdbus_cal_factory_activate (&err)) {
+ UNLOCK_FACTORY ();
if (err) {
unwrap_dbus_error (err, &err);
g_warning ("%s: Failed to run calendar factory: %s", G_STRFUNC, err->message);
xml = e_source_to_standalone_xml (source);
if (!xml || !*xml) {
+ UNLOCK_FACTORY ();
g_free (xml);
g_set_error_literal (error, E_CLIENT_ERROR, E_CLIENT_ERROR_INVALID_ARG, _("Invalid source"));
return NULL;
strv = e_gdbus_cal_factory_encode_get_cal (xml, convert_type (source_type));
if (!strv) {
+ UNLOCK_FACTORY ();
g_free (xml);
g_set_error_literal (error, E_CLIENT_ERROR, E_CLIENT_ERROR_OTHER_ERROR, _("Other error"));
return NULL;
client = g_object_new (E_TYPE_CAL_CLIENT, "source", source, NULL);
client->priv->source_type = source_type;
+ UNLOCK_FACTORY ();
+
if (!e_gdbus_cal_factory_call_get_cal_sync (G_DBUS_PROXY (cal_factory_proxy), (const gchar * const *) strv, &path, NULL, &err)) {
unwrap_dbus_error (err, &err);
g_free (xml);
}
}
-static gchar *
-cal_client_retrieve_capabilities (EClient *client)
+static void
+cal_client_retrieve_capabilities (EClient *client, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data)
{
ECalClient *cal_client;
- GError *error = NULL;
- gchar *capabilities = NULL;
- g_return_val_if_fail (client != NULL, NULL);
+ g_return_if_fail (client != NULL);
cal_client = E_CAL_CLIENT (client);
- g_return_val_if_fail (cal_client != NULL, NULL);
- g_return_val_if_fail (cal_client->priv != NULL, NULL);
+ g_return_if_fail (cal_client != NULL);
+ g_return_if_fail (cal_client->priv != NULL);
- if (!cal_client->priv->gdbus_cal)
- return NULL;
+ cal_client_get_backend_property (client, CLIENT_BACKEND_PROPERTY_CAPABILITIES, cancellable, callback, user_data);
+}
+
+static gboolean
+cal_client_retrieve_capabilities_finish (EClient *client, GAsyncResult *result, gchar **capabilities, GError **error)
+{
+ ECalClient *cal_client;
- e_gdbus_cal_call_get_backend_property_sync (cal_client->priv->gdbus_cal, CLIENT_BACKEND_PROPERTY_CAPABILITIES, &capabilities, NULL, &error);
+ g_return_val_if_fail (client != NULL, FALSE);
- if (error) {
- g_debug ("%s: Failed to retrieve capabilitites: %s", G_STRFUNC, error->message);
- g_error_free (error);
- }
+ cal_client = E_CAL_CLIENT (client);
+ g_return_val_if_fail (cal_client != NULL, FALSE);
+ g_return_val_if_fail (cal_client->priv != NULL, FALSE);
+
+ return cal_client_get_backend_property_finish (client, result, capabilities, error);
+}
+
+static gboolean
+cal_client_retrieve_capabilities_sync (EClient *client, gchar **capabilities, GCancellable *cancellable, GError **error)
+{
+ ECalClient *cal_client;
+
+ g_return_val_if_fail (client != NULL, FALSE);
+
+ cal_client = E_CAL_CLIENT (client);
+ g_return_val_if_fail (cal_client != NULL, FALSE);
+ g_return_val_if_fail (cal_client->priv != NULL, FALSE);
- return capabilities;
+ return cal_client_get_backend_property_sync (client, CLIENT_BACKEND_PROPERTY_CAPABILITIES, capabilities, cancellable, error);
}
static void
client_class->unwrap_dbus_error = cal_client_unwrap_dbus_error;
client_class->handle_authentication = cal_client_handle_authentication;
client_class->retrieve_capabilities = cal_client_retrieve_capabilities;
+ client_class->retrieve_capabilities_finish = cal_client_retrieve_capabilities_finish;
+ client_class->retrieve_capabilities_sync = cal_client_retrieve_capabilities_sync;
client_class->get_backend_property = cal_client_get_backend_property;
client_class->get_backend_property_finish = cal_client_get_backend_property_finish;
client_class->get_backend_property_sync = cal_client_get_backend_property_sync;
static void
client_ensure_capabilities (EClient *client)
{
- EClientClass *klass;
gchar *capabilities;
g_return_if_fail (client != NULL);
g_return_if_fail (E_IS_CLIENT (client));
g_return_if_fail (client->priv != NULL);
- klass = E_CLIENT_GET_CLASS (client);
- g_return_if_fail (klass != NULL);
- g_return_if_fail (klass->retrieve_capabilities != NULL);
-
if (client->priv->capabilities_retrieved || client->priv->capabilities)
return;
g_static_rec_mutex_lock (&client->priv->prop_mutex);
- capabilities = klass->retrieve_capabilities (client);
-
- e_client_set_capabilities (client, capabilities);
-
+ capabilities = NULL;
+ e_client_retrieve_capabilities_sync (client, &capabilities, NULL, NULL);
+ /* e_client_set_capabilities is called inside the previous function */
g_free (capabilities);
client->priv->capabilities_retrieved = TRUE;
}
/**
+ * e_client_retrieve_capabilities:
+ * @client: an #EClient
+ * @cancellable: a #GCancellable; can be %NULL
+ * @callback: callback to call when a result is ready
+ * @user_data: user data for the @callback
+ *
+ * Initiates retrieval of capabilities on the @client. This is usually
+ * required only once, after the @client is opened. The returned value
+ * is cached and any subsequent call of e_client_get_capabilities() and
+ * e_client_check_capability() is using the cached value.
+ * The call is finished by e_client_retrieve_capabilities_finish()
+ * from the @callback.
+ *
+ * Since: 3.2
+ **/
+void
+e_client_retrieve_capabilities (EClient *client, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data)
+{
+ EClientClass *klass;
+
+ g_return_if_fail (client != NULL);
+ g_return_if_fail (E_IS_CLIENT (client));
+ g_return_if_fail (client->priv != NULL);
+ g_return_if_fail (callback != NULL);
+
+ klass = E_CLIENT_GET_CLASS (client);
+ g_return_if_fail (klass != NULL);
+ g_return_if_fail (klass->retrieve_capabilities != NULL);
+
+ klass->retrieve_capabilities (client, cancellable, callback, user_data);
+}
+
+/**
+ * e_client_retrieve_capabilities_finish:
+ * @client: an #EClient
+ * @result: a #GAsyncResult
+ * @capabilities: (out): Comma-separated list of capabilities of the @client
+ * @error: (out): a #GError to set an error, if any
+ *
+ * Finishes previous call of e_client_retrieve_capabilities().
+ * Returned value of @capabilities should be freed with g_free(),
+ * when no longer needed.
+ *
+ * Returns: %TRUE if successful, %FALSE otherwise.
+ *
+ * Since: 3.2
+ **/
+gboolean
+e_client_retrieve_capabilities_finish (EClient *client, GAsyncResult *result, gchar **capabilities, GError **error)
+{
+ EClientClass *klass;
+ gboolean res;
+
+ g_return_val_if_fail (client != NULL, FALSE);
+ g_return_val_if_fail (E_IS_CLIENT (client), FALSE);
+ g_return_val_if_fail (client->priv != NULL, FALSE);
+ g_return_val_if_fail (capabilities != NULL, FALSE);
+
+ klass = E_CLIENT_GET_CLASS (client);
+ g_return_val_if_fail (klass != NULL, FALSE);
+ g_return_val_if_fail (klass->retrieve_capabilities_finish != NULL, FALSE);
+
+ *capabilities = NULL;
+ res = klass->retrieve_capabilities_finish (client, result, capabilities, error);
+
+ e_client_set_capabilities (client, res ? *capabilities : NULL);
+
+ return res;
+}
+
+/**
+ * e_client_retrieve_capabilities_sync:
+ * @client: an #EClient
+ * @capabilities: (out): Comma-separated list of capabilities of the @client
+ * @cancellable: a #GCancellable; can be %NULL
+ * @error: (out): a #GError to set an error, if any
+ *
+ * Initiates retrieval of capabilities on the @client. This is usually
+ * required only once, after the @client is opened. The returned value
+ * is cached and any subsequent call of e_client_get_capabilities() and
+ * e_client_check_capability() is using the cached value. Returned value
+ * of @capabilities should be freed with g_free(), when no longer needed.
+ *
+ * Returns: %TRUE if successful, %FALSE otherwise.
+ *
+ * Since: 3.2
+ **/
+gboolean
+e_client_retrieve_capabilities_sync (EClient *client, gchar **capabilities, GCancellable *cancellable, GError **error)
+{
+ EClientClass *klass;
+ gboolean res = FALSE;
+
+ g_return_val_if_fail (client != NULL, FALSE);
+ g_return_val_if_fail (capabilities != NULL, FALSE);
+
+ klass = E_CLIENT_GET_CLASS (client);
+ g_return_val_if_fail (klass != NULL, FALSE);
+ g_return_val_if_fail (klass->retrieve_capabilities_sync != NULL, FALSE);
+
+ *capabilities = NULL;
+ res = klass->retrieve_capabilities_sync (client, capabilities, cancellable, error);
+
+ e_client_set_capabilities (client, res ? *capabilities : NULL);
+
+ return res;
+}
+
+/**
* e_client_get_backend_property:
* @client: an #EClient
* @prop_name: property name, whose value to retrieve; cannot be %NULL
GDBusProxy * (* get_dbus_proxy) (EClient *client);
void (* unwrap_dbus_error) (EClient *client, GError *dbus_error, GError **out_error);
+ void (* retrieve_capabilities) (EClient *client, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data);
+ gboolean (* retrieve_capabilities_finish) (EClient *client, GAsyncResult *result, gchar **capabilities, GError **error);
+ gboolean (* retrieve_capabilities_sync) (EClient *client, gchar **capabilities, GCancellable *cancellable, GError **error);
+
void (* get_backend_property) (EClient *client, const gchar *prop_name, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data);
gboolean (* get_backend_property_finish) (EClient *client, GAsyncResult *result, gchar **prop_value, GError **error);
gboolean (* get_backend_property_sync) (EClient *client, const gchar *prop_name, gchar **prop_value, GCancellable *cancellable, GError **error);
gboolean (* refresh_sync) (EClient *client, GCancellable *cancellable, GError **error);
void (* handle_authentication) (EClient *client, const ECredentials *credentials);
- gchar * (* retrieve_capabilities) (EClient *client);
/* signals */
gboolean (* authenticate) (EClient *client, ECredentials *credentials);
gboolean e_client_refresh_finish (EClient *client, GAsyncResult *result, GError **error);
gboolean e_client_refresh_sync (EClient *client, GCancellable *cancellable, GError **error);
+void e_client_retrieve_capabilities (EClient *client, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data);
+gboolean e_client_retrieve_capabilities_finish (EClient *client, GAsyncResult *result, gchar **capabilities, GError **error);
+gboolean e_client_retrieve_capabilities_sync (EClient *client, gchar **capabilities, GCancellable *cancellable, GError **error);
+
/* utility functions */
gchar ** e_client_util_slist_to_strv (const GSList *strings);
GSList * e_client_util_strv_to_slist (const gchar * const *strv);
}
static void
-client_utils_open_new_done (EClientUtilsAsyncOpData *async_data)
+client_utils_capabilities_retrieved_cb (GObject *source_object, GAsyncResult *result, gpointer user_data)
{
+ EClient *client = E_CLIENT (source_object);
+ EClientUtilsAsyncOpData *async_data = user_data;
+ gchar *capabilities = NULL;
GSimpleAsyncResult *simple;
g_return_if_fail (async_data != NULL);
g_return_if_fail (async_data->client != NULL);
+ g_return_if_fail (async_data->client == client);
+
+ e_client_retrieve_capabilities_finish (client, result, &capabilities, NULL);
+ g_free (capabilities);
/* keep the initial auth_handler connected directly, thus it will be able
to answer any later authentication requests, for reconnection, for example
}
static void
+client_utils_open_new_done (EClientUtilsAsyncOpData *async_data)
+{
+ g_return_if_fail (async_data != NULL);
+ g_return_if_fail (async_data->client != NULL);
+
+ /* retrieve capabilities just to have them cached on #EClient for later use */
+ e_client_retrieve_capabilities (async_data->client, async_data->cancellable, client_utils_capabilities_retrieved_cb, async_data);
+}
+
+static void
client_utils_open_new_cancelled_cb (GCancellable *cancellable, EClientUtilsAsyncOpData *async_data)
{
GError *error = NULL;
e_client_process_authentication (async_data->client, async_data->used_credentials);
} else if (error && g_error_matches (error, E_CLIENT_ERROR, E_CLIENT_ERROR_BUSY)) {
- /* postpone for few 1/4 of a second, backend is busy now */
+ /* postpone for 1/2 of a second, backend is busy now */
async_data->retry_open_id = g_timeout_add (500, client_utils_retry_open_timeout_cb, async_data);
} else if (error) {
return_async_error (error, async_data->async_cb, async_data->async_cb_user_data, async_data->source, e_client_utils_open_new);
* Begins asynchronous opening of a new #EClient corresponding
* to the @source of type @source_type. The resulting #EClient
* is fully opened and authenticated client, ready to be used.
+ * The opened client has also fetched capabilities.
* This call is finished by e_client_utils_open_new_finish()
* from the @async_cb.
*
{
GSList *prop_names = NULL;
- prop_names = g_slist_append (prop_names, (gpointer) CLIENT_BACKEND_PROPERTY_OPENED);
- prop_names = g_slist_append (prop_names, (gpointer) CLIENT_BACKEND_PROPERTY_OPENING);
- prop_names = g_slist_append (prop_names, (gpointer) CLIENT_BACKEND_PROPERTY_ONLINE);
prop_names = g_slist_append (prop_names, (gpointer) CLIENT_BACKEND_PROPERTY_READONLY);
+ prop_names = g_slist_append (prop_names, (gpointer) CLIENT_BACKEND_PROPERTY_ONLINE);
+ prop_names = g_slist_append (prop_names, (gpointer) CLIENT_BACKEND_PROPERTY_OPENING);
+ prop_names = g_slist_append (prop_names, (gpointer) CLIENT_BACKEND_PROPERTY_OPENED);
prop_names = g_slist_append (prop_names, (gpointer) CLIENT_BACKEND_PROPERTY_CACHE_DIR);
prop_names = g_slist_append (prop_names, (gpointer) CLIENT_BACKEND_PROPERTY_CAPABILITIES);
prop_names = g_slist_append (prop_names, (gpointer) BOOK_BACKEND_PROPERTY_REQUIRED_FIELDS);
{
GSList *prop_names = NULL;
+ prop_names = g_slist_append (prop_names, (gpointer) CLIENT_BACKEND_PROPERTY_READONLY);
+ prop_names = g_slist_append (prop_names, (gpointer) CLIENT_BACKEND_PROPERTY_ONLINE);
prop_names = g_slist_append (prop_names, (gpointer) CLIENT_BACKEND_PROPERTY_OPENED);
prop_names = g_slist_append (prop_names, (gpointer) CLIENT_BACKEND_PROPERTY_OPENING);
- prop_names = g_slist_append (prop_names, (gpointer) CLIENT_BACKEND_PROPERTY_ONLINE);
- prop_names = g_slist_append (prop_names, (gpointer) CLIENT_BACKEND_PROPERTY_READONLY);
prop_names = g_slist_append (prop_names, (gpointer) CLIENT_BACKEND_PROPERTY_CACHE_DIR);
prop_names = g_slist_append (prop_names, (gpointer) CLIENT_BACKEND_PROPERTY_CAPABILITIES);
prop_names = g_slist_append (prop_names, (gpointer) CAL_BACKEND_PROPERTY_CAL_EMAIL_ADDRESS);
{
GSList *prop_names = NULL;
+ prop_names = g_slist_append (prop_names, (gpointer) CLIENT_BACKEND_PROPERTY_READONLY);
+ prop_names = g_slist_append (prop_names, (gpointer) CLIENT_BACKEND_PROPERTY_ONLINE);
prop_names = g_slist_append (prop_names, (gpointer) CLIENT_BACKEND_PROPERTY_OPENED);
prop_names = g_slist_append (prop_names, (gpointer) CLIENT_BACKEND_PROPERTY_OPENING);
- prop_names = g_slist_append (prop_names, (gpointer) CLIENT_BACKEND_PROPERTY_ONLINE);
- prop_names = g_slist_append (prop_names, (gpointer) CLIENT_BACKEND_PROPERTY_READONLY);
prop_names = g_slist_append (prop_names, (gpointer) CLIENT_BACKEND_PROPERTY_CACHE_DIR);
prop_names = g_slist_append (prop_names, (gpointer) CLIENT_BACKEND_PROPERTY_CAPABILITIES);
GError *error = NULL;
EClient *client = NULL;
- g_return_if_fail (source_object == NULL);
+ g_return_if_fail (source_object != NULL);
+ g_return_if_fail (E_IS_SOURCE (source_object));
g_return_if_fail (async_data != NULL);
if (!e_client_utils_open_new_finish (E_SOURCE (source_object), result, &client, &error)) {