4 * This library is free software you can redistribute it and/or modify it
5 * under the terms of the GNU Lesser General Public License as published by
6 * the Free Software Foundation.
8 * This library is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
10 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13 * You should have received a copy of the GNU Lesser General Public License
14 * along with this library; if not, see <http://www.gnu.org/licenses/>.
20 * @include: libebackend/libebackend.h
21 * @short_description: An abstract base class for backends
23 * An #EBackend is paired with an #ESource to facilitate performing
24 * actions on the local or remote resource described by the #ESource.
26 * In other words, whereas a certain backend type knows how to talk to a
27 * certain type of server or data store, the #ESource fills in configuration
28 * details such as host name, user name, resource path, etc.
30 * All #EBackend instances are created by an #EBackendFactory.
34 #include <glib/gi18n-lib.h>
38 #include <libedataserver/libedataserver.h>
40 #include "e-backend.h"
41 #include "e-user-prompter.h"
43 #define E_BACKEND_GET_PRIVATE(obj) \
44 (G_TYPE_INSTANCE_GET_PRIVATE \
45 ((obj), E_TYPE_BACKEND, EBackendPrivate))
47 #define G_IS_IO_ERROR(error, code) \
48 (g_error_matches ((error), G_IO_ERROR, (code)))
50 #define G_IS_RESOLVER_ERROR(error, code) \
51 (g_error_matches ((error), G_RESOLVER_ERROR, (code)))
53 typedef struct _AsyncContext AsyncContext;
55 struct _EBackendPrivate {
58 EUserPrompter *prompter;
59 GMainContext *main_context;
60 GSocketConnectable *connectable;
63 GNetworkMonitor *network_monitor;
64 gulong network_changed_handler_id;
66 GSource *update_online_state;
67 GMutex update_online_state_lock;
69 GMutex network_monitor_cancellable_lock;
70 GCancellable *network_monitor_cancellable;
73 struct _AsyncContext {
74 ESourceAuthenticator *auth;
86 G_DEFINE_ABSTRACT_TYPE (EBackend, e_backend, G_TYPE_OBJECT)
89 async_context_free (AsyncContext *async_context)
91 if (async_context->auth != NULL)
92 g_object_unref (async_context->auth);
94 g_slice_free (AsyncContext, async_context);
98 backend_network_monitor_can_reach_cb (GObject *source_object,
102 EBackend *backend = E_BACKEND (user_data);
103 gboolean host_is_reachable;
104 GError *error = NULL;
106 host_is_reachable = g_network_monitor_can_reach_finish (
107 G_NETWORK_MONITOR (source_object), result, &error);
111 (host_is_reachable && (error == NULL)) ||
112 (!host_is_reachable && (error != NULL)));
114 if (G_IS_IO_ERROR (error, G_IO_ERROR_CANCELLED) ||
115 host_is_reachable == e_backend_get_online (backend)) {
116 g_clear_error (&error);
117 g_object_unref (backend);
121 g_clear_error (&error);
123 e_backend_set_online (backend, host_is_reachable);
125 g_object_unref (backend);
129 backend_update_online_state_idle_cb (gpointer user_data)
132 GSocketConnectable *connectable;
133 GCancellable *cancellable;
135 backend = E_BACKEND (user_data);
136 connectable = e_backend_ref_connectable (backend);
138 g_mutex_lock (&backend->priv->update_online_state_lock);
139 g_source_unref (backend->priv->update_online_state);
140 backend->priv->update_online_state = NULL;
141 g_mutex_unlock (&backend->priv->update_online_state_lock);
143 g_mutex_lock (&backend->priv->network_monitor_cancellable_lock);
145 cancellable = backend->priv->network_monitor_cancellable;
146 backend->priv->network_monitor_cancellable = NULL;
148 if (cancellable != NULL) {
149 g_cancellable_cancel (cancellable);
150 g_object_unref (cancellable);
158 if (e_backend_get_destination_address (backend, &host, &port) && host)
159 connectable = g_network_address_new (host, port);
164 if (connectable == NULL) {
165 e_backend_set_online (backend, TRUE);
167 cancellable = g_cancellable_new ();
169 g_network_monitor_can_reach_async (
170 backend->priv->network_monitor,
171 connectable, cancellable,
172 backend_network_monitor_can_reach_cb,
173 g_object_ref (backend));
176 backend->priv->network_monitor_cancellable = cancellable;
178 g_mutex_unlock (&backend->priv->network_monitor_cancellable_lock);
180 if (connectable != NULL)
181 g_object_unref (connectable);
187 backend_update_online_state (EBackend *backend)
189 g_mutex_lock (&backend->priv->update_online_state_lock);
191 if (backend->priv->update_online_state == NULL) {
192 GMainContext *main_context;
193 GSource *idle_source;
195 main_context = e_backend_ref_main_context (backend);
197 idle_source = g_idle_source_new ();
198 g_source_set_priority (idle_source, G_PRIORITY_LOW);
199 g_source_set_callback (
201 backend_update_online_state_idle_cb,
202 g_object_ref (backend),
203 (GDestroyNotify) g_object_unref);
204 g_source_attach (idle_source, main_context);
205 backend->priv->update_online_state =
206 g_source_ref (idle_source);
207 g_source_unref (idle_source);
209 g_main_context_unref (main_context);
212 g_mutex_unlock (&backend->priv->update_online_state_lock);
216 backend_network_changed_cb (GNetworkMonitor *network_monitor,
217 gboolean network_available,
220 backend_update_online_state (backend);
224 backend_set_source (EBackend *backend,
227 g_return_if_fail (E_IS_SOURCE (source));
228 g_return_if_fail (backend->priv->source == NULL);
230 backend->priv->source = g_object_ref (source);
234 backend_set_property (GObject *object,
239 switch (property_id) {
240 case PROP_CONNECTABLE:
241 e_backend_set_connectable (
243 g_value_get_object (value));
247 e_backend_set_online (
249 g_value_get_boolean (value));
255 g_value_get_object (value));
259 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
263 backend_get_property (GObject *object,
268 switch (property_id) {
269 case PROP_CONNECTABLE:
270 g_value_take_object (
271 value, e_backend_ref_connectable (
272 E_BACKEND (object)));
275 case PROP_MAIN_CONTEXT:
277 value, e_backend_ref_main_context (
278 E_BACKEND (object)));
282 g_value_set_boolean (
283 value, e_backend_get_online (
284 E_BACKEND (object)));
289 value, e_backend_get_source (
290 E_BACKEND (object)));
293 case PROP_USER_PROMPTER:
295 value, e_backend_get_user_prompter (
296 E_BACKEND (object)));
300 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
304 backend_dispose (GObject *object)
306 EBackendPrivate *priv;
308 priv = E_BACKEND_GET_PRIVATE (object);
310 if (priv->network_changed_handler_id > 0) {
311 g_signal_handler_disconnect (
312 priv->network_monitor,
313 priv->network_changed_handler_id);
314 priv->network_changed_handler_id = 0;
317 if (priv->main_context != NULL) {
318 g_main_context_unref (priv->main_context);
319 priv->main_context = NULL;
322 if (priv->update_online_state != NULL) {
323 g_source_destroy (priv->update_online_state);
324 g_source_unref (priv->update_online_state);
325 priv->update_online_state = NULL;
328 g_clear_object (&priv->source);
329 g_clear_object (&priv->prompter);
330 g_clear_object (&priv->connectable);
331 g_clear_object (&priv->network_monitor);
332 g_clear_object (&priv->network_monitor_cancellable);
334 /* Chain up to parent's dispose() method. */
335 G_OBJECT_CLASS (e_backend_parent_class)->dispose (object);
339 backend_finalize (GObject *object)
341 EBackendPrivate *priv;
343 priv = E_BACKEND_GET_PRIVATE (object);
345 g_mutex_clear (&priv->property_lock);
346 g_mutex_clear (&priv->update_online_state_lock);
347 g_mutex_clear (&priv->network_monitor_cancellable_lock);
349 /* Chain up to parent's finalize() method. */
350 G_OBJECT_CLASS (e_backend_parent_class)->finalize (object);
354 backend_constructed (GObject *object)
358 const gchar *extension_name;
360 backend = E_BACKEND (object);
362 /* Chain up to parent's constructed() method. */
363 G_OBJECT_CLASS (e_backend_parent_class)->constructed (object);
365 /* Get an initial GSocketConnectable from the data
366 * source's [Authentication] extension, if present. */
367 source = e_backend_get_source (backend);
368 extension_name = E_SOURCE_EXTENSION_AUTHENTICATION;
369 if (e_source_has_extension (source, extension_name)) {
370 ESourceAuthentication *extension;
372 extension = e_source_get_extension (source, extension_name);
374 backend->priv->connectable =
375 e_source_authentication_ref_connectable (extension);
377 backend_update_online_state (backend);
382 backend_authenticate_thread (GSimpleAsyncResult *simple,
384 GCancellable *cancellable)
386 AsyncContext *async_context;
387 GError *error = NULL;
389 async_context = g_simple_async_result_get_op_res_gpointer (simple);
391 e_backend_authenticate_sync (
394 cancellable, &error);
397 g_simple_async_result_take_error (simple, error);
401 backend_authenticate_sync (EBackend *backend,
402 ESourceAuthenticator *auth,
403 GCancellable *cancellable,
407 error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
408 _("%s does not support authentication"),
409 G_OBJECT_TYPE_NAME (backend));
415 backend_authenticate (EBackend *backend,
416 ESourceAuthenticator *auth,
417 GCancellable *cancellable,
418 GAsyncReadyCallback callback,
421 GSimpleAsyncResult *simple;
422 AsyncContext *async_context;
424 async_context = g_slice_new0 (AsyncContext);
425 async_context->auth = g_object_ref (auth);
427 simple = g_simple_async_result_new (
428 G_OBJECT (backend), callback,
429 user_data, backend_authenticate);
431 g_simple_async_result_set_check_cancellable (simple, cancellable);
433 g_simple_async_result_set_op_res_gpointer (
434 simple, async_context, (GDestroyNotify) async_context_free);
436 g_simple_async_result_run_in_thread (
437 simple, backend_authenticate_thread,
438 G_PRIORITY_DEFAULT, cancellable);
440 g_object_unref (simple);
444 backend_authenticate_finish (EBackend *backend,
445 GAsyncResult *result,
448 GSimpleAsyncResult *simple;
450 g_return_val_if_fail (
451 g_simple_async_result_is_valid (
452 result, G_OBJECT (backend),
453 backend_authenticate), FALSE);
455 simple = G_SIMPLE_ASYNC_RESULT (result);
457 /* Assume success unless a GError is set. */
458 return !g_simple_async_result_propagate_error (simple, error);
462 backend_get_destination_address (EBackend *backend,
466 /* default implementation returns FALSE, indicating
467 * no remote destination being used for this backend */
472 e_backend_class_init (EBackendClass *class)
474 GObjectClass *object_class;
476 g_type_class_add_private (class, sizeof (EBackendPrivate));
478 object_class = G_OBJECT_CLASS (class);
479 object_class->set_property = backend_set_property;
480 object_class->get_property = backend_get_property;
481 object_class->dispose = backend_dispose;
482 object_class->finalize = backend_finalize;
483 object_class->constructed = backend_constructed;
485 class->authenticate_sync = backend_authenticate_sync;
486 class->authenticate = backend_authenticate;
487 class->authenticate_finish = backend_authenticate_finish;
488 class->get_destination_address = backend_get_destination_address;
490 g_object_class_install_property (
493 g_param_spec_object (
496 "Socket endpoint of a network service",
497 G_TYPE_SOCKET_CONNECTABLE,
499 G_PARAM_STATIC_STRINGS));
501 g_object_class_install_property (
507 "The main loop context on "
508 "which to attach event sources",
511 G_PARAM_STATIC_STRINGS));
513 g_object_class_install_property (
516 g_param_spec_boolean (
519 "Whether the backend is online",
523 G_PARAM_STATIC_STRINGS));
525 g_object_class_install_property (
528 g_param_spec_object (
531 "The data source being acted upon",
534 G_PARAM_CONSTRUCT_ONLY |
535 G_PARAM_STATIC_STRINGS));
537 g_object_class_install_property (
540 g_param_spec_object (
543 "User prompter instance",
544 E_TYPE_USER_PROMPTER,
546 G_PARAM_STATIC_STRINGS));
550 e_backend_init (EBackend *backend)
552 GNetworkMonitor *network_monitor;
555 backend->priv = E_BACKEND_GET_PRIVATE (backend);
556 backend->priv->prompter = e_user_prompter_new ();
557 backend->priv->main_context = g_main_context_ref_thread_default ();
559 g_mutex_init (&backend->priv->property_lock);
560 g_mutex_init (&backend->priv->update_online_state_lock);
561 g_mutex_init (&backend->priv->network_monitor_cancellable_lock);
563 /* Configure network monitoring. */
565 network_monitor = g_network_monitor_get_default ();
566 backend->priv->network_monitor = g_object_ref (network_monitor);
568 handler_id = g_signal_connect (
569 backend->priv->network_monitor, "network-changed",
570 G_CALLBACK (backend_network_changed_cb), backend);
571 backend->priv->network_changed_handler_id = handler_id;
575 * e_backend_get_online:
576 * @backend: an #EBackend
578 * Returns the online state of @backend: %TRUE if @backend is online,
581 * If the #EBackend:connectable property is non-%NULL, the @backend will
582 * automatically determine whether the network service should be reachable,
583 * and hence whether the @backend is #EBackend:online. But subclasses may
584 * override the online state if, for example, a connection attempt fails.
586 * Returns: the online state
591 e_backend_get_online (EBackend *backend)
593 g_return_val_if_fail (E_IS_BACKEND (backend), FALSE);
595 return backend->priv->online;
599 * e_backend_set_online:
600 * @backend: an #EBackend
601 * @online: the online state
603 * Sets the online state of @backend: %TRUE if @backend is online,
606 * If the #EBackend:connectable property is non-%NULL, the @backend will
607 * automatically determine whether the network service should be reachable,
608 * and hence whether the @backend is #EBackend:online. But subclasses may
609 * override the online state if, for example, a connection attempt fails.
614 e_backend_set_online (EBackend *backend,
617 g_return_if_fail (E_IS_BACKEND (backend));
619 /* Avoid unnecessary "notify" signals. */
620 if (backend->priv->online == online)
623 backend->priv->online = online;
625 /* Cancel any automatic "online" state update in progress. */
626 g_mutex_lock (&backend->priv->network_monitor_cancellable_lock);
627 g_cancellable_cancel (backend->priv->network_monitor_cancellable);
628 g_mutex_unlock (&backend->priv->network_monitor_cancellable_lock);
630 g_object_notify (G_OBJECT (backend), "online");
634 * e_backend_get_source:
635 * @backend: an #EBackend
637 * Returns the #ESource to which @backend is paired.
639 * Returns: the #ESource to which @backend is paired
644 e_backend_get_source (EBackend *backend)
646 g_return_val_if_fail (E_IS_BACKEND (backend), NULL);
648 return backend->priv->source;
652 * e_backend_ref_connectable:
653 * @backend: an #EBackend
655 * Returns the socket endpoint for the network service to which @backend
656 * is a client, or %NULL if @backend does not use network sockets.
658 * The initial value of the #EBackend:connectable property is derived from
659 * the #ESourceAuthentication extension of the @backend's #EBackend:source
660 * property, if the extension is present.
662 * The returned #GSocketConnectable is referenced for thread-safety and
663 * must be unreferenced with g_object_unref() when finished with it.
665 * Returns: a #GSocketConnectable, or %NULL
670 e_backend_ref_connectable (EBackend *backend)
672 GSocketConnectable *connectable = NULL;
674 g_return_val_if_fail (E_IS_BACKEND (backend), NULL);
676 g_mutex_lock (&backend->priv->property_lock);
678 if (backend->priv->connectable != NULL)
679 connectable = g_object_ref (backend->priv->connectable);
681 g_mutex_unlock (&backend->priv->property_lock);
687 * e_backend_set_connectable:
688 * @backend: an #EBackend
689 * @connectable: a #GSocketConnectable, or %NULL
691 * Sets the socket endpoint for the network service to which @backend is
692 * a client. This can be %NULL if @backend does not use network sockets.
694 * The initial value of the #EBackend:connectable property is derived from
695 * the #ESourceAuthentication extension of the @backend's #EBackend:source
696 * property, if the extension is present.
701 e_backend_set_connectable (EBackend *backend,
702 GSocketConnectable *connectable)
704 g_return_if_fail (E_IS_BACKEND (backend));
706 if (connectable != NULL) {
707 g_return_if_fail (G_IS_SOCKET_CONNECTABLE (connectable));
708 g_object_ref (connectable);
711 g_mutex_lock (&backend->priv->property_lock);
713 if (backend->priv->connectable != NULL)
714 g_object_unref (backend->priv->connectable);
716 backend->priv->connectable = connectable;
718 g_mutex_unlock (&backend->priv->property_lock);
720 backend_update_online_state (backend);
722 g_object_notify (G_OBJECT (backend), "connectable");
726 * e_backend_ref_main_context:
727 * @backend: an #EBackend
729 * Returns the #GMainContext on which event sources for @backend are to
732 * The returned #GMainContext is referenced for thread-safety and must be
733 * unreferenced with g_main_context_unref() when finished with it.
735 * Returns: (transfer full): a #GMainContext
740 e_backend_ref_main_context (EBackend *backend)
742 g_return_val_if_fail (E_IS_BACKEND (backend), NULL);
744 return g_main_context_ref (backend->priv->main_context);
748 * e_backend_authenticate_sync:
749 * @backend: an #EBackend
750 * @auth: an #ESourceAuthenticator
751 * @cancellable: optional #GCancellable object, or %NULL
752 * @error: return location for a #GError, or %NULL
754 * Convenience function providing a consistent authentication interface
755 * for backends running in either the registry service itself or a client
756 * process communicating with the registry service over D-Bus.
758 * Authenticates @backend's #EBackend:source, using @auth to handle
759 * authentication attempts. The @backend and @auth arguments may be one
760 * and the same if @backend implements the #ESourceAuthenticator interface.
761 * The operation loops until authentication is successful or the user aborts
762 * further authentication attempts. If an error occurs, the function will
763 * set @error and return %FALSE.
765 * Returns: %TRUE on success, %FALSE on failure
770 e_backend_authenticate_sync (EBackend *backend,
771 ESourceAuthenticator *auth,
772 GCancellable *cancellable,
775 EBackendClass *class;
777 g_return_val_if_fail (E_IS_BACKEND (backend), FALSE);
778 g_return_val_if_fail (E_IS_SOURCE_AUTHENTICATOR (auth), FALSE);
780 class = E_BACKEND_GET_CLASS (backend);
781 g_return_val_if_fail (class->authenticate_sync != NULL, FALSE);
783 return class->authenticate_sync (backend, auth, cancellable, error);
787 * e_backend_authenticate:
788 * @backend: an #EBackend
789 * @auth: an #ESourceAuthenticator
790 * @cancellable: optional #GCancellable object, or %NULL
791 * @callback: a #GAsyncReadyCallback to call when the request is satisfied
792 * @user_data: data to pass to the callback function
794 * Convenience function providing a consistent authentication interface
795 * for backends running in either the registry service itself or a client
796 * process communicating with the registry service over D-Bus.
798 * Asynchronously authenticates @backend's #EBackend:source, using @auth
799 * to handle authentication attempts. The @backend and @auth arguments may
800 * be one and the same if @backend implements the #ESourceAuthenticator
801 * interface. The operation loops until authentication is succesful or the
802 * user aborts further authentication attempts.
804 * When the operation is finished, @callback will be called. You can then
805 * call e_backend_authenticate_finish() to get the result of the operation.
810 e_backend_authenticate (EBackend *backend,
811 ESourceAuthenticator *auth,
812 GCancellable *cancellable,
813 GAsyncReadyCallback callback,
816 EBackendClass *class;
818 g_return_if_fail (E_IS_BACKEND (backend));
819 g_return_if_fail (E_IS_SOURCE_AUTHENTICATOR (auth));
821 class = E_BACKEND_GET_CLASS (backend);
822 g_return_if_fail (class->authenticate != NULL);
824 class->authenticate (backend, auth, cancellable, callback, user_data);
828 * e_backend_authenticate_finish:
829 * @backend: an #EBackend
830 * @result: a #GAsyncResult
831 * @error: return location for a #GError, or %NULL
833 * Finishes the operation started with e_backend_authenticate(). If
834 * an error occurred, the function will set @error and return %FALSE.
836 * Returns: %TRUE on success, %FALSE on failure
841 e_backend_authenticate_finish (EBackend *backend,
842 GAsyncResult *result,
845 EBackendClass *class;
847 g_return_val_if_fail (E_IS_BACKEND (backend), FALSE);
848 g_return_val_if_fail (G_IS_ASYNC_RESULT (result), FALSE);
850 class = E_BACKEND_GET_CLASS (backend);
851 g_return_val_if_fail (class->authenticate_finish != NULL, FALSE);
853 return class->authenticate_finish (backend, result, error);
857 * e_backend_get_user_prompter:
858 * @backend: an #EBackend
860 * Gets an instance of #EUserPrompter, associated with this @backend.
862 * The returned instance is owned by the @backend.
864 * Returns: (transfer none): an #EUserPrompter instance
869 e_backend_get_user_prompter (EBackend *backend)
871 g_return_val_if_fail (E_IS_BACKEND (backend), NULL);
873 return backend->priv->prompter;
877 * e_backend_trust_prompt_sync:
878 * @backend: an #EBackend
879 * @parameters: an #ENamedParameters with values for the trust prompt
880 * @cancellable: (allow-none): optional #GCancellable object, or %NULL
881 * @error: return location for a #GError, or %NULL
883 * Asks a user a trust prompt with given @parameters, and returns what
884 * user responded. This blocks until the response is delivered.
886 * Returns: an #ETrustPromptResponse what user responded
888 * Note: The function can return also %E_TRUST_PROMPT_RESPONSE_UNKNOWN,
889 * it's on error or if user closes the trust prompt dialog with other
890 * than the offered buttons. Usual behaviour in such case is to treat
891 * it as a temporary reject.
896 e_backend_trust_prompt_sync (EBackend *backend,
897 const ENamedParameters *parameters,
898 GCancellable *cancellable,
901 EUserPrompter *prompter;
904 g_return_val_if_fail (
905 E_IS_BACKEND (backend), E_TRUST_PROMPT_RESPONSE_UNKNOWN);
906 g_return_val_if_fail (
907 parameters != NULL, E_TRUST_PROMPT_RESPONSE_UNKNOWN);
909 prompter = e_backend_get_user_prompter (backend);
910 g_return_val_if_fail (
911 prompter != NULL, E_TRUST_PROMPT_RESPONSE_UNKNOWN);
913 response = e_user_prompter_extension_prompt_sync (
914 prompter, "ETrustPrompt::trust-prompt",
915 parameters, NULL, cancellable, error);
918 return E_TRUST_PROMPT_RESPONSE_REJECT;
920 return E_TRUST_PROMPT_RESPONSE_ACCEPT;
922 return E_TRUST_PROMPT_RESPONSE_ACCEPT_TEMPORARILY;
924 return E_TRUST_PROMPT_RESPONSE_REJECT_TEMPORARILY;
926 return E_TRUST_PROMPT_RESPONSE_UNKNOWN;
930 * e_backend_trust_prompt:
931 * @backend: an #EBackend
932 * @parameters: an #ENamedParameters with values for the trust prompt
933 * @cancellable: (allow-none): optional #GCancellable object, or %NULL
934 * @callback: a #GAsyncReadyCallback to call when the request is satisfied
935 * @user_data: data to pass to the callback function
937 * Initiates a user trust prompt with given @parameters.
939 * When the operation is finished, @callback will be called. You can then
940 * call e_backend_trust_prompt_finish() to get the result of the operation.
945 e_backend_trust_prompt (EBackend *backend,
946 const ENamedParameters *parameters,
947 GCancellable *cancellable,
948 GAsyncReadyCallback callback,
951 EUserPrompter *prompter;
953 g_return_if_fail (E_IS_BACKEND (backend));
954 g_return_if_fail (parameters != NULL);
956 prompter = e_backend_get_user_prompter (backend);
957 g_return_if_fail (prompter != NULL);
959 e_user_prompter_extension_prompt (
960 prompter, "ETrustPrompt::trust-prompt",
961 parameters, cancellable, callback, user_data);
965 * e_backend_trust_prompt_finish:
966 * @backend: an #EBackend
967 * @result: a #GAsyncResult
968 * @error: return location for a #GError, or %NULL
970 * Finishes the operation started with e_backend_trust_prompt().
971 * If an error occurred, the function will set @error and return
972 * %E_TRUST_PROMPT_RESPONSE_UNKNOWN.
974 * Returns: an #ETrustPromptResponse what user responded
976 * Note: The function can return also %E_TRUST_PROMPT_RESPONSE_UNKNOWN,
977 * it's on error or if user closes the trust prompt dialog with other
978 * than the offered buttons. Usual behaviour in such case is to treat
979 * it as a temporary reject.
984 e_backend_trust_prompt_finish (EBackend *backend,
985 GAsyncResult *result,
988 EUserPrompter *prompter;
991 g_return_val_if_fail (
992 E_IS_BACKEND (backend), E_TRUST_PROMPT_RESPONSE_UNKNOWN);
994 prompter = e_backend_get_user_prompter (backend);
995 g_return_val_if_fail (
996 prompter != NULL, E_TRUST_PROMPT_RESPONSE_UNKNOWN);
998 response = e_user_prompter_extension_prompt_finish (
999 prompter, result, NULL, error);
1002 return E_TRUST_PROMPT_RESPONSE_REJECT;
1004 return E_TRUST_PROMPT_RESPONSE_ACCEPT;
1006 return E_TRUST_PROMPT_RESPONSE_ACCEPT_TEMPORARILY;
1008 return E_TRUST_PROMPT_RESPONSE_REJECT_TEMPORARILY;
1010 return E_TRUST_PROMPT_RESPONSE_UNKNOWN;
1014 * e_backend_get_destination_address:
1015 * @backend: an #EBackend instance
1016 * @host: (out): destination server host name
1017 * @port: (out): destination server port
1019 * Provides destination server host name and port to which
1020 * the backend connects. This is used to determine required
1021 * connection point for e_backend_destination_is_reachable().
1022 * The @host is a newly allocated string, which will be freed
1023 * with g_free(). When @backend sets both @host and @port, then
1024 * it should return %TRUE, indicating it's a remote backend.
1025 * Default implementation returns %FALSE, which is treated
1026 * like the backend is local, no checking for server reachability
1029 * Returns: %TRUE, when it's a remote backend and provides both
1030 * @host and @port; %FALSE otherwise.
1035 e_backend_get_destination_address (EBackend *backend,
1039 EBackendClass *klass;
1041 g_return_val_if_fail (E_IS_BACKEND (backend), FALSE);
1042 g_return_val_if_fail (host != NULL, FALSE);
1043 g_return_val_if_fail (port != NULL, FALSE);
1045 klass = E_BACKEND_GET_CLASS (backend);
1046 g_return_val_if_fail (klass->get_destination_address != NULL, FALSE);
1048 return klass->get_destination_address (backend, host, port);
1052 * e_backend_is_destination_reachable:
1053 * @backend: an #EBackend instance
1054 * @cancellable: a #GCancellable instance, or %NULL
1055 * @error: a #GError for errors, or %NULL
1057 * Checks whether the @backend<!-- -->'s destination server, as returned
1058 * by e_backend_get_destination_address(), is reachable.
1059 * If the e_backend_get_destination_address() returns %FALSE, this function
1060 * returns %TRUE, meaning the destination is always reachable.
1061 * This uses #GNetworkMonitor<!-- -->'s g_network_monitor_can_reach()
1062 * for reachability tests.
1064 * Returns: %TRUE, when destination server address is reachable or
1065 * the backend doesn't provide destination address; %FALSE if
1066 * the backend destination server cannot be reached currently.
1071 e_backend_is_destination_reachable (EBackend *backend,
1072 GCancellable *cancellable,
1075 gboolean reachable = TRUE;
1079 g_return_val_if_fail (E_IS_BACKEND (backend), FALSE);
1081 if (e_backend_get_destination_address (backend, &host, &port)) {
1082 g_warn_if_fail (host != NULL);
1085 GNetworkMonitor *network_monitor;
1086 GSocketConnectable *connectable;
1088 network_monitor = backend->priv->network_monitor;
1090 connectable = g_network_address_new (host, port);
1092 reachable = g_network_monitor_can_reach (
1093 network_monitor, connectable,
1094 cancellable, error);
1095 g_object_unref (connectable);