111
120
e_source_registry_server,
112
121
E_TYPE_DATA_FACTORY)
124
auth_request_new (EAuthenticationSession *session,
125
GSimpleAsyncResult *simple,
126
GCancellable *cancellable)
128
ESourceRegistryServer *server;
129
AuthRequest *request;
132
server = e_authentication_session_get_server (session);
133
uid = e_authentication_session_get_source_uid (session);
135
request = g_slice_new0 (AuthRequest);
136
request->ref_count = 1;
137
request->session = g_object_ref (session);
138
request->simple = g_object_ref (simple);
140
/* This will return NULL if the authenticating data source
141
* has not yet been submitted to the D-Bus registry server. */
142
request->source = e_source_registry_server_ref_source (server, uid);
144
if (G_IS_CANCELLABLE (cancellable))
145
request->cancellable = g_object_ref (cancellable);
151
auth_request_ref (AuthRequest *request)
153
g_return_val_if_fail (request != NULL, NULL);
154
g_return_val_if_fail (request->ref_count > 0, NULL);
156
g_atomic_int_inc (&request->ref_count);
162
auth_request_unref (AuthRequest *request)
164
g_return_if_fail (request != NULL);
165
g_return_if_fail (request->ref_count > 0);
167
if (g_atomic_int_dec_and_test (&request->ref_count)) {
169
g_object_unref (request->session);
170
g_object_unref (request->simple);
172
if (request->source != NULL)
173
g_object_unref (request->source);
175
if (request->cancellable != NULL)
176
g_object_unref (request->cancellable);
178
g_slice_free (AuthRequest, request);
114
182
/* GDestroyNotify callback for 'sources' values */
116
184
unref_data_source (ESource *source)
307
source_registry_server_auth_table_lookup (ESourceRegistryServer *server,
310
GHashTable *hash_table;
375
source_request_server_auth_request_cancel_all (ESourceRegistryServer *server)
380
g_mutex_lock (server->priv->auth_lock);
382
g_hash_table_iter_init (&iter, server->priv->waiting_auths);
384
while (g_hash_table_iter_next (&iter, NULL, &value)) {
385
GQueue *queue = value;
388
list = g_queue_peek_head_link (queue);
390
for (link = list; link != NULL; link = g_list_next (link)) {
391
AuthRequest *request = link->data;
392
g_cancellable_cancel (request->cancellable);
396
g_hash_table_iter_init (&iter, server->priv->running_auths);
398
while (g_hash_table_iter_next (&iter, NULL, &value)) {
399
AuthRequest *request = value;
400
g_cancellable_cancel (request->cancellable);
403
g_mutex_unlock (server->priv->auth_lock);
407
source_registry_server_auth_request_push (ESourceRegistryServer *server,
409
AuthRequest *request)
313
hash_table = server->priv->auth_table;
314
queue = g_hash_table_lookup (hash_table, uid);
413
g_return_if_fail (uid != NULL);
415
g_mutex_lock (server->priv->auth_lock);
417
queue = g_hash_table_lookup (server->priv->waiting_auths, uid);
316
419
if (queue == NULL) {
317
420
queue = g_queue_new ();
318
g_hash_table_insert (hash_table, g_strdup (uid), queue);
421
g_hash_table_insert (
422
server->priv->waiting_auths,
423
g_strdup (uid), queue);
426
g_queue_push_tail (queue, auth_request_ref (request));
428
g_mutex_unlock (server->priv->auth_lock);
432
source_registry_server_auth_request_next (ESourceRegistryServer *server,
435
AuthRequest *request = NULL;
437
g_return_val_if_fail (uid != NULL, NULL);
439
g_mutex_lock (server->priv->auth_lock);
441
/* If we're already busy processing an authentication request
442
* for this UID, the next request will have to wait in line. */
443
if (!g_hash_table_contains (server->priv->running_auths, uid)) {
446
queue = g_hash_table_lookup (
447
server->priv->waiting_auths, uid);
450
request = g_queue_pop_head (queue);
453
g_hash_table_insert (
454
server->priv->running_auths,
456
auth_request_ref (request));
459
g_mutex_unlock (server->priv->auth_lock);
465
source_registry_server_auth_request_done (ESourceRegistryServer *server,
468
g_return_if_fail (uid != NULL);
470
g_mutex_lock (server->priv->auth_lock);
472
g_hash_table_remove (server->priv->running_auths, uid);
474
g_mutex_unlock (server->priv->auth_lock);
326
479
GAsyncResult *result,
327
480
gpointer user_data)
482
ESourceRegistryServer *server;
329
483
EAuthenticationSession *session;
330
ESourceRegistryServer *server;
331
484
EAuthenticationSessionResult auth_result;
485
AuthRequest *request;
333
486
const gchar *uid;
334
487
GError *error = NULL;
336
489
session = E_AUTHENTICATION_SESSION (source_object);
337
server = E_SOURCE_REGISTRY_SERVER (user_data);
490
request = (AuthRequest *) user_data;
339
492
auth_result = e_authentication_session_execute_finish (
340
493
session, result, &error);
342
495
if (error != NULL) {
343
g_warning ("%s: %s", G_STRFUNC, error->message);
344
g_error_free (error);
496
g_warn_if_fail (auth_result == E_AUTHENTICATION_SESSION_ERROR);
497
g_simple_async_result_take_error (request->simple, error);
347
uid = e_authentication_session_get_source_uid (session);
348
g_return_if_fail (uid != NULL);
350
/* Authentication dismissals may require additional handling. */
500
/* Authentication dismissals require additional handling. */
351
501
if (auth_result == E_AUTHENTICATION_SESSION_DISMISSED) {
352
502
ESourceAuthenticator *authenticator;
355
504
/* If the authenticator is an EAuthenticationMediator,
356
505
* have it emit a "dismissed" signal to the client. */
360
509
e_authentication_mediator_dismiss (
361
510
E_AUTHENTICATION_MEDIATOR (authenticator));
363
/* This will return NULL if the authenticating data source
364
* has not yet been submitted to the D-Bus registry service. */
365
source = e_source_registry_server_ref_source (server, uid);
366
if (source != NULL) {
367
/* Prevent further user interruptions. */
512
/* Prevent further user interruptions. */
513
if (request->source != NULL)
368
514
e_server_side_source_set_allow_auth_prompt (
369
E_SERVER_SIDE_SOURCE (source), FALSE);
370
g_object_unref (source);
515
E_SERVER_SIDE_SOURCE (request->source), FALSE);
517
/* e_source_registry_server_authenticate_finish() should
518
* return an error since authentication did not complete. */
519
g_simple_async_result_set_error (
521
G_IO_ERROR, G_IO_ERROR_CANCELLED,
522
_("The user declined to authenticate"));
374
queue = source_registry_server_auth_table_lookup (server, uid);
376
/* Remove the completed auth session from its queue. */
377
if (g_queue_remove (queue, session))
378
g_object_unref (session);
380
/* If the completed auth session was the active one,
381
* clear the active pointer for the next auth session. */
382
if (session == server->priv->active_auth)
383
server->priv->active_auth = NULL;
385
source_registry_server_maybe_start_auth_session (server);
387
g_object_unref (server);
525
g_simple_async_result_complete_in_idle (request->simple);
527
server = e_authentication_session_get_server (session);
528
uid = e_authentication_session_get_source_uid (session);
530
source_registry_server_auth_request_done (server, uid);
531
source_registry_server_maybe_start_auth_session (server, uid);
533
auth_request_unref (request);
391
source_registry_server_maybe_start_auth_session (ESourceRegistryServer *server)
537
source_registry_server_start_auth_session_idle_cb (gpointer user_data)
395
if (server->priv->active_auth != NULL)
398
if (g_cancellable_is_cancelled (server->priv->auth_cancellable))
401
/* Check if there's any authenticators left in the active
402
* auth table queue. If the user provided a valid secret
403
* and elected to save it in the keyring, or if the user
404
* dismissed the authentication prompt, then we should be
405
* able to process the remaining authenticators quickly. */
406
if (server->priv->active_auth_table_queue != NULL &&
407
!g_queue_is_empty (server->priv->active_auth_table_queue)) {
408
queue = server->priv->active_auth_table_queue;
409
server->priv->active_auth = g_queue_peek_head (queue);
411
/* Otherwise find the next non-empty auth table queue to
412
* be processed, according to the UIDs in the auth queue. */
413
} else while (!g_queue_is_empty (server->priv->auth_queue)) {
416
uid = g_queue_pop_head (server->priv->auth_queue);
417
queue = source_registry_server_auth_table_lookup (server, uid);
420
if (!g_queue_is_empty (queue)) {
421
server->priv->active_auth_table_queue = queue;
422
server->priv->active_auth = g_queue_peek_head (queue);
427
/* Initiate the new active authenicator. This signals it to
539
AuthRequest *request = user_data;
541
/* Execute the new active auth session. This signals it to
428
542
* respond with a cached secret in the keyring if it can, or
429
543
* else show an authentication prompt and wait for input. */
430
if (server->priv->active_auth != NULL)
431
e_authentication_session_execute (
432
server->priv->active_auth,
434
server->priv->auth_cancellable,
435
source_registry_server_auth_session_cb,
436
g_object_ref (server));
438
server->priv->active_auth_table_queue = NULL;
544
e_authentication_session_execute (
547
request->cancellable,
548
source_registry_server_auth_session_cb,
549
auth_request_ref (request));
555
source_registry_server_maybe_start_auth_session (ESourceRegistryServer *server,
558
AuthRequest *request;
560
/* We own the returned reference, unless we get NULL. */
561
request = source_registry_server_auth_request_next (server, uid);
563
if (request != NULL) {
564
GSource *idle_source;
566
/* Process the next AuthRequest from an idle callback
567
* on our own GMainContext, since the current thread-
568
* default GMainContext may only be temporary. */
569
idle_source = g_idle_source_new ();
570
g_source_set_callback (
572
source_registry_server_start_auth_session_idle_cb,
573
auth_request_ref (request),
574
(GDestroyNotify) auth_request_unref);
575
g_source_attach (idle_source, server->priv->main_context);
576
g_source_unref (idle_source);
578
auth_request_unref (request);
583
source_registry_server_authenticate_done_cb (GObject *source_object,
584
GAsyncResult *result,
587
GError *error = NULL;
589
e_source_registry_server_authenticate_finish (
590
E_SOURCE_REGISTRY_SERVER (source_object), result, &error);
592
/* Ignore cancellations. */
593
if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) {
594
g_error_free (error);
596
} else if (error != NULL) {
597
g_warning ("%s: %s", G_STRFUNC, error->message);
598
g_error_free (error);
1354
* e_source_registry_server_queue_auth_session:
1355
* @server: an #ESourceRegistryServer
1356
* @session: an #EDBusSourceAuthenticator
1358
* Queues an authentication session. When its turn comes, and if necessary,
1359
* the user will be prompted for a secret. Sessions are queued this way to
1360
* prevent user prompts from piling up on the screen.
1365
e_source_registry_server_queue_auth_session (ESourceRegistryServer *server,
1366
EAuthenticationSession *session)
1371
g_return_if_fail (E_IS_SOURCE_REGISTRY_SERVER (server));
1372
g_return_if_fail (E_IS_AUTHENTICATION_SESSION (session));
1374
uid = e_authentication_session_get_source_uid (session);
1375
g_return_if_fail (uid != NULL);
1377
/* Add the session to the appropriate queue. */
1378
queue = source_registry_server_auth_table_lookup (server, uid);
1379
g_queue_push_tail (queue, g_object_ref (session));
1381
/* Blindly push the UID onto the processing queue. */
1382
g_queue_push_tail (server->priv->auth_queue, g_strdup (uid));
1384
source_registry_server_maybe_start_auth_session (server);
1388
1552
* e_source_registry_server_load_all:
1389
1553
* @server: an #ESourceRegistryServer
1390
1554
* @error: return location for a #GError, or %NULL
1919
* e_source_registry_server_ref_backend:
1920
* @server: an #ESourceRegistryServer
1921
* @source: an #ESource
1923
* Returns the #ECollectionBackend associated with @source, or %NULL if
1924
* there is no #ECollectionBackend associated with @source.
1926
* An #ESource is associated with an #ECollectionBackend if the #ESource has
1927
* an #ESourceCollection extension, or if it is a hierarchical descendant of
1928
* another #ESource which has an #ESourceCollection extension.
1930
* The returned #ECollectionBackend is referenced for thread-safety.
1931
* Unreference the #ECollectionBackend with g_object_unref() when finished
1934
* Returns: the #ECollectionBackend for @source, or %NULL
1938
ECollectionBackend *
1939
e_source_registry_server_ref_backend (ESourceRegistryServer *server,
1942
ECollectionBackend *backend = NULL;
1943
const gchar *extension_name;
1945
g_return_val_if_fail (E_IS_SOURCE_REGISTRY_SERVER (server), NULL);
1946
g_return_val_if_fail (E_IS_SOURCE (source), NULL);
1948
/* XXX If ESourceRegistryServer ever grows a function similar to
1949
* e_source_registry_find_extension() then we could just use
1950
* that, but despite this use case I think the need for such
1951
* a function is not sufficiently strong yet. */
1953
extension_name = E_SOURCE_EXTENSION_COLLECTION;
1955
g_object_ref (source);
1957
while (!e_source_has_extension (source, extension_name)) {
1960
uid = e_source_dup_parent (source);
1962
g_object_unref (source);
1966
source = e_source_registry_server_ref_source (
1975
if (source != NULL) {
1976
backend = g_object_get_data (
1977
G_OBJECT (source), BACKEND_DATA_KEY);
1978
if (backend != NULL)
1979
g_object_ref (backend);
1980
g_object_unref (source);
1755
1987
* e_source_registry_server_ref_backend_factory:
1756
1988
* @server: an #ESourceRegistryServer
1757
1989
* @source: an #ESource
1805
2037
return E_COLLECTION_BACKEND_FACTORY (factory);
2041
* e_source_registry_server_authenticate_sync:
2042
* @server: an #ESourceRegistryServer
2043
* @session: an #EAuthenticationSession
2044
* @cancellable: optional #GCancellable object, or %NULL
2045
* @error: return location for a #GError, or %NULL
2047
* Queues the @session behind any ongoing or pending authentication
2048
* sessions for the same data source, and eventually executes @session
2049
* (see e_authentication_session_execute_sync() for more details).
2051
* This function blocks until @session is finished executing. For a
2052
* non-blocking variation see e_source_registry_server_authenticate().
2054
* If an error occurs, the function sets @error and returns %FALSE.
2056
* Returns: %TRUE on success, %FALSE on failure
2061
e_source_registry_server_authenticate_sync (ESourceRegistryServer *server,
2062
EAuthenticationSession *session,
2063
GCancellable *cancellable,
2066
EAsyncClosure *closure;
2067
GAsyncResult *result;
2070
g_return_val_if_fail (E_IS_SOURCE_REGISTRY_SERVER (server), FALSE);
2071
g_return_val_if_fail (E_IS_AUTHENTICATION_SESSION (session), FALSE);
2073
closure = e_async_closure_new ();
2075
e_source_registry_server_authenticate (
2076
server, session, cancellable,
2077
e_async_closure_callback, closure);
2079
result = e_async_closure_wait (closure);
2081
success = e_source_registry_server_authenticate_finish (
2082
server, result, error);
2084
e_async_closure_free (closure);
2090
* e_source_registry_server_authenticate:
2091
* @server: an #ESourceRegistryServer
2092
* @session: an #EAuthenticationSession
2093
* @cancellable: optional #GCancellable object, or %NULL
2094
* @callback: a #GAsyncReadyCallback to call when the request is satisfied
2095
* @user_data: data to pass to the callback function
2097
* Queues the @session behind any ongoing or pending authentication
2098
* sessions for the same data source, and eventually executes @session
2099
* (see e_authentication_session_execute_sync() for more details).
2101
* This function returns immediately after enqueuing @session. When
2102
* @session is finished executing, @callback will be called. You can
2103
* then call e_source_registry_server_authenticate_finish() to get the
2104
* result of the operation.
2109
e_source_registry_server_authenticate (ESourceRegistryServer *server,
2110
EAuthenticationSession *session,
2111
GCancellable *cancellable,
2112
GAsyncReadyCallback callback,
2115
GSimpleAsyncResult *simple;
2116
AuthRequest *request;
2119
g_return_if_fail (E_IS_SOURCE_REGISTRY_SERVER (server));
2120
g_return_if_fail (E_IS_AUTHENTICATION_SESSION (session));
2122
uid = e_authentication_session_get_source_uid (session);
2123
g_return_if_fail (uid != NULL);
2125
simple = g_simple_async_result_new (
2126
G_OBJECT (server), callback, user_data,
2127
e_source_registry_server_authenticate);
2129
g_simple_async_result_set_check_cancellable (simple, cancellable);
2131
request = auth_request_new (session, simple, cancellable);
2132
source_registry_server_auth_request_push (server, uid, request);
2133
auth_request_unref (request);
2135
source_registry_server_maybe_start_auth_session (server, uid);
2137
g_object_unref (simple);
2141
* e_source_registry_server_authenticate_finish:
2142
* @server: an #ESourceRegistryServer
2143
* @result: a #GAsyncResult
2144
* @error: return location for a #GError, or %NULL
2146
* Finishes the operation started with e_source_registry_server_authenticate().
2147
* If an error occurred, the function will set @error and return %FALSE.
2149
* Returns: %TRUE on success, %FALSE on failure
2154
e_source_registry_server_authenticate_finish (ESourceRegistryServer *server,
2155
GAsyncResult *result,
2158
GSimpleAsyncResult *simple;
2160
g_return_val_if_fail (
2161
g_simple_async_result_is_valid (
2162
result, G_OBJECT (server),
2163
e_source_registry_server_authenticate), FALSE);
2165
simple = G_SIMPLE_ASYNC_RESULT (result);
2167
/* Assume success unless a GError is set. */
2168
return !g_simple_async_result_propagate_error (simple, error);