1 /* GIO - GLib Input, Output and Streaming Library
2 *
3 * Copyright (C) 2006-2007 Red Hat, Inc.
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General
16 * Public License along with this library; if not, write to the
17 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 * Boston, MA 02110-1301, USA.
19 *
20 * Author: Alexander Larsson <alexl@redhat.com>
21 */
22
23 #include <config.h>
24
25 #include <gmountsource.h>
26 #include <gio/gio.h>
27 #include <gvfsdbus.h>
28 #include "gvfsdaemonprotocol.h"
29
30 #include <string.h>
31
32 struct _GMountSource
33 {
34 GObject parent_instance;
35
36 char *dbus_id;
37 char *obj_path;
38 };
39
G_DEFINE_TYPE(GMountSource,g_mount_source,G_TYPE_OBJECT)40 G_DEFINE_TYPE (GMountSource, g_mount_source, G_TYPE_OBJECT)
41
42 static void
43 g_mount_source_finalize (GObject *object)
44 {
45 GMountSource *source;
46
47 source = G_MOUNT_SOURCE (object);
48
49 g_free (source->dbus_id);
50 g_free (source->obj_path);
51
52 if (G_OBJECT_CLASS (g_mount_source_parent_class)->finalize)
53 (*G_OBJECT_CLASS (g_mount_source_parent_class)->finalize) (object);
54 }
55
56 static void
g_mount_source_class_init(GMountSourceClass * klass)57 g_mount_source_class_init (GMountSourceClass *klass)
58 {
59 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
60
61 gobject_class->finalize = g_mount_source_finalize;
62 }
63
64 static void
g_mount_source_init(GMountSource * mount_source)65 g_mount_source_init (GMountSource *mount_source)
66 {
67 }
68
69 GMountSource *
g_mount_source_new(const char * dbus_id,const char * obj_path)70 g_mount_source_new (const char *dbus_id,
71 const char *obj_path)
72 {
73 GMountSource *source;
74
75 source = g_object_new (G_TYPE_MOUNT_SOURCE, NULL);
76
77 source->dbus_id = g_strdup (dbus_id);
78 source->obj_path = g_strdup (obj_path);
79
80 return source;
81 }
82
83 GMountSource *
g_mount_source_new_dummy(void)84 g_mount_source_new_dummy (void)
85 {
86 GMountSource *source;
87
88 source = g_object_new (G_TYPE_MOUNT_SOURCE, NULL);
89
90 source->dbus_id = g_strdup ("");
91 source->obj_path = g_strdup ("/");
92
93 return source;
94 }
95
96 GVariant *
g_mount_source_to_dbus(GMountSource * source)97 g_mount_source_to_dbus (GMountSource *source)
98 {
99 g_assert (source->dbus_id != NULL);
100 g_assert (source->obj_path != NULL);
101
102 return g_variant_new ("(so)",
103 source->dbus_id,
104 source->obj_path);
105 }
106
107 GMountSource *
g_mount_source_from_dbus(GVariant * value)108 g_mount_source_from_dbus (GVariant *value)
109 {
110 const gchar *obj_path, *dbus_id;
111
112 g_variant_get (value, "(&s&o)",
113 &dbus_id,
114 &obj_path);
115
116 return g_mount_source_new (dbus_id, obj_path);
117 }
118
119 const char *
g_mount_source_get_dbus_id(GMountSource * mount_source)120 g_mount_source_get_dbus_id (GMountSource *mount_source)
121 {
122 return mount_source->dbus_id;
123 }
124
125 const char *
g_mount_source_get_obj_path(GMountSource * mount_source)126 g_mount_source_get_obj_path (GMountSource *mount_source)
127 {
128 return mount_source->obj_path;
129 }
130
131 typedef struct AskPasswordData AskPasswordData;
132
133 struct AskPasswordData {
134
135 /* results: */
136 gboolean aborted;
137 char *password;
138 char *username;
139 char *domain;
140 GPasswordSave password_save;
141 gboolean anonymous;
142 };
143
144 typedef struct AskSyncData AskSyncData;
145
146 struct AskSyncData {
147
148 /* For sync calls */
149 GMainContext *context;
150 GMainLoop *loop;
151
152 /* results: */
153 GAsyncResult *result;
154 };
155
156 static void
ask_password_data_free(gpointer _data)157 ask_password_data_free (gpointer _data)
158 {
159 AskPasswordData *data = (AskPasswordData *) _data;
160 g_free (data->password);
161 g_free (data->username);
162 g_free (data->domain);
163 g_free (data);
164 }
165
166 static GVfsDBusMountOperation *
create_mount_operation_proxy_sync(GMountSource * source,GError ** error)167 create_mount_operation_proxy_sync (GMountSource *source,
168 GError **error)
169 {
170 GVfsDBusMountOperation *proxy;
171 GError *local_error;
172
173 /* If no dbus id specified, reply that we weren't handled */
174 if (source->dbus_id[0] == 0)
175 {
176 g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, "Internal Error");
177 return NULL;
178 }
179
180 local_error = NULL;
181 /* Synchronously creating a proxy using unique/private d-bus name and not loading properties or connecting signals should not block */
182 proxy = gvfs_dbus_mount_operation_proxy_new_for_bus_sync (G_BUS_TYPE_SESSION,
183 G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS | G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES,
184 source->dbus_id,
185 source->obj_path,
186 NULL,
187 &local_error);
188 if (proxy == NULL)
189 {
190 g_dbus_error_strip_remote_error (local_error);
191 g_propagate_error (error, local_error);
192 }
193
194 return proxy;
195 }
196
197 /* the callback from dbus -> main thread */
198 static void
ask_password_reply(GVfsDBusMountOperation * proxy,GAsyncResult * res,gpointer user_data)199 ask_password_reply (GVfsDBusMountOperation *proxy,
200 GAsyncResult *res,
201 gpointer user_data)
202 {
203 GTask *task;
204 AskPasswordData *data;
205 gboolean handled, aborted, anonymous;
206 guint32 password_save;
207 gchar *password, *username, *domain;
208 GError *error;
209
210 task = G_TASK (user_data);
211 handled = TRUE;
212
213 error = NULL;
214 if (!gvfs_dbus_mount_operation_call_ask_password_finish (proxy,
215 &handled,
216 &aborted,
217 &password,
218 &username,
219 &domain,
220 &anonymous,
221 &password_save,
222 res,
223 &error))
224 {
225 g_dbus_error_strip_remote_error (error);
226 g_task_return_error (task, error);
227 }
228 else if (handled == FALSE)
229 {
230 g_task_return_new_error (task, G_IO_ERROR, G_IO_ERROR_FAILED, "Internal Error");
231 }
232 else
233 {
234 data = g_new0 (AskPasswordData, 1);
235 data->aborted = aborted;
236
237 if (!anonymous)
238 {
239 data->password = g_strdup (password);
240 data->username = *username == 0 ? NULL : g_strdup (username);
241 data->domain = *domain == 0 ? NULL : g_strdup (domain);
242 }
243 data->password_save = (GPasswordSave)password_save;
244 data->anonymous = anonymous;
245
246 g_task_return_pointer (task, data, ask_password_data_free);
247
248 /* TODO: handle more args */
249 g_free (password);
250 g_free (username);
251 g_free (domain);
252 }
253
254 g_object_unref (task);
255 }
256
257 void
g_mount_source_ask_password_async(GMountSource * source,const char * message_string,const char * default_user,const char * default_domain,GAskPasswordFlags flags,GAsyncReadyCallback callback,gpointer user_data)258 g_mount_source_ask_password_async (GMountSource *source,
259 const char *message_string,
260 const char *default_user,
261 const char *default_domain,
262 GAskPasswordFlags flags,
263 GAsyncReadyCallback callback,
264 gpointer user_data)
265 {
266 GTask *task;
267 GVfsDBusMountOperation *proxy;
268 GError *error = NULL;
269
270 task = g_task_new (source, NULL, callback, user_data);
271 g_task_set_source_tag (task, g_mount_source_ask_password_async);
272
273 proxy = create_mount_operation_proxy_sync (source, &error);
274 if (proxy == NULL)
275 {
276 g_task_return_error (task, error);
277 g_object_unref (task);
278 return;
279 }
280
281 /* 30 minute timeout */
282 g_dbus_proxy_set_default_timeout (G_DBUS_PROXY (proxy), G_VFS_DBUS_MOUNT_TIMEOUT_MSECS);
283
284 gvfs_dbus_mount_operation_call_ask_password (proxy,
285 message_string ? message_string : "",
286 default_user ? default_user : "",
287 default_domain ? default_domain : "",
288 flags,
289 NULL,
290 (GAsyncReadyCallback) ask_password_reply,
291 task);
292 g_object_unref (proxy);
293 }
294
295 /**
296 * g_mount_source_ask_password_finish:
297 * @source: the source to query
298 * @result: the async result
299 * @aborted: set to %TRUE if the password dialog was aborted by the user
300 * @password_out: the to the password set by the user or to %NULL if none
301 * @user_out: set to the username set by the user or to %NULL if none
302 * @domain_out: set to the domain set by the user or to %NULL if none
303 * @anonymous_out: set to %TRUE if the user selected anonymous login. This
304 * should only happen if G_ASK_PASSWORD_ANONYMOUS_SUPPORTED
305 * was supplied whe querying the password.
306 * @password_save_out: set to the save flags to use when saving the password
307 * in the keyring.
308 *
309 * Requests the reply parameters from a g_mount_source_ask_password_async()
310 * request. All out parameters can be set to %NULL to ignore them.
311 * <note><para>Please be aware that out parameters other than the password
312 * are set to %NULL if the user don't specify them so make sure to
313 * check them.</para></note>
314 *
315 * Returns: %FALSE if the async reply contained an error.
316 **/
317 gboolean
g_mount_source_ask_password_finish(GMountSource * source,GAsyncResult * result,gboolean * aborted,char ** password_out,char ** user_out,char ** domain_out,gboolean * anonymous_out,GPasswordSave * password_save_out)318 g_mount_source_ask_password_finish (GMountSource *source,
319 GAsyncResult *result,
320 gboolean *aborted,
321 char **password_out,
322 char **user_out,
323 char **domain_out,
324 gboolean *anonymous_out,
325 GPasswordSave *password_save_out)
326 {
327 AskPasswordData *data, def = { TRUE, };
328
329 g_return_val_if_fail (g_task_is_valid (result, source), FALSE);
330 g_return_val_if_fail (g_async_result_is_tagged (result, g_mount_source_ask_password_async), FALSE);
331
332 data = g_task_propagate_pointer (G_TASK (result), NULL);
333 if (data == NULL)
334 data = &def;
335
336 if (aborted)
337 *aborted = data->aborted;
338
339 if (password_out)
340 {
341 *password_out = data->password;
342 data->password = NULL;
343 }
344
345 if (user_out)
346 {
347 *user_out = data->username;
348 data->username = NULL;
349 }
350
351 if (domain_out)
352 {
353 *domain_out = data->domain;
354 data->domain = NULL;
355 }
356
357 if (anonymous_out)
358 *anonymous_out = data->anonymous;
359
360 if (password_save_out)
361 *password_save_out = data->password_save;
362
363 return data != &def;
364 }
365
366
367 static void
ask_reply_sync(GObject * source_object,GAsyncResult * res,gpointer user_data)368 ask_reply_sync (GObject *source_object,
369 GAsyncResult *res,
370 gpointer user_data)
371 {
372 AskSyncData *data;
373
374 data = (AskSyncData *) user_data;
375
376 data->result = g_object_ref (res);
377
378 g_main_loop_quit (data->loop);
379 }
380
381 gboolean
g_mount_source_ask_password(GMountSource * source,const char * message_string,const char * default_user,const char * default_domain,GAskPasswordFlags flags,gboolean * aborted_out,char ** password_out,char ** user_out,char ** domain_out,gboolean * anonymous_out,GPasswordSave * password_save_out)382 g_mount_source_ask_password (GMountSource *source,
383 const char *message_string,
384 const char *default_user,
385 const char *default_domain,
386 GAskPasswordFlags flags,
387 gboolean *aborted_out,
388 char **password_out,
389 char **user_out,
390 char **domain_out,
391 gboolean *anonymous_out,
392 GPasswordSave *password_save_out)
393 {
394 gboolean handled;
395 AskSyncData data;
396
397 data.context = g_main_context_new ();
398 data.loop = g_main_loop_new (data.context, FALSE);
399
400 g_main_context_push_thread_default (data.context);
401
402 g_mount_source_ask_password_async (source,
403 message_string,
404 default_user,
405 default_domain,
406 flags,
407 ask_reply_sync,
408 &data);
409
410 g_main_loop_run (data.loop);
411
412 handled = g_mount_source_ask_password_finish (source,
413 data.result,
414 aborted_out,
415 password_out,
416 user_out,
417 domain_out,
418 anonymous_out,
419 password_save_out);
420
421 g_main_context_pop_thread_default (data.context);
422 g_main_context_unref (data.context);
423 g_main_loop_unref (data.loop);
424 g_object_unref (data.result);
425
426 return handled;
427 }
428
429 static void
op_ask_password_reply(GObject * source_object,GAsyncResult * res,gpointer user_data)430 op_ask_password_reply (GObject *source_object,
431 GAsyncResult *res,
432 gpointer user_data)
433 {
434 GMountOperationResult result;
435 GMountOperation *op;
436 GMountSource *source;
437 gboolean handled, aborted;
438 char *username;
439 char *password;
440 char *domain;
441 GPasswordSave password_save;
442
443 source = G_MOUNT_SOURCE (source_object);
444 op = G_MOUNT_OPERATION (user_data);
445 username = NULL;
446 password = NULL;
447 domain = NULL;
448
449 handled = g_mount_source_ask_password_finish (source,
450 res,
451 &aborted,
452 &password,
453 &username,
454 &domain,
455 NULL,
456 &password_save);
457
458 if (!handled)
459 result = G_MOUNT_OPERATION_UNHANDLED;
460 else if (aborted)
461 result = G_MOUNT_OPERATION_ABORTED;
462 else
463 {
464 result = G_MOUNT_OPERATION_HANDLED;
465
466 if (password)
467 g_mount_operation_set_password (op, password);
468 if (username)
469 g_mount_operation_set_username (op, username);
470 if (domain)
471 g_mount_operation_set_domain (op, domain);
472 g_mount_operation_set_password_save (op, password_save);
473 }
474
475 g_mount_operation_reply (op, result);
476 g_object_unref (op);
477 }
478
479 static gboolean
op_ask_password(GMountOperation * op,const char * message,const char * default_user,const char * default_domain,GAskPasswordFlags flags,GMountSource * mount_source)480 op_ask_password (GMountOperation *op,
481 const char *message,
482 const char *default_user,
483 const char *default_domain,
484 GAskPasswordFlags flags,
485 GMountSource *mount_source)
486 {
487 g_mount_source_ask_password_async (mount_source,
488 message,
489 default_user,
490 default_domain,
491 flags,
492 op_ask_password_reply,
493 g_object_ref (op));
494 g_signal_stop_emission_by_name (op, "ask_password");
495 return TRUE;
496 }
497
498 typedef struct AskQuestionData AskQuestionData;
499
500 struct AskQuestionData {
501
502 /* results: */
503 gboolean aborted;
504 guint32 choice;
505 };
506
507 /* the callback from dbus -> main thread */
508 static void
ask_question_reply(GVfsDBusMountOperation * proxy,GAsyncResult * res,gpointer user_data)509 ask_question_reply (GVfsDBusMountOperation *proxy,
510 GAsyncResult *res,
511 gpointer user_data)
512 {
513 GTask *task;
514 AskQuestionData *data;
515 gboolean handled, aborted;
516 guint32 choice;
517 GError *error;
518
519 task = G_TASK (user_data);
520 handled = TRUE;
521
522 error = NULL;
523 if (!gvfs_dbus_mount_operation_call_ask_question_finish (proxy,
524 &handled,
525 &aborted,
526 &choice,
527 res,
528 &error))
529 {
530 g_dbus_error_strip_remote_error (error);
531 g_task_return_error (task, error);
532 }
533 else if (handled == FALSE)
534 {
535 g_task_return_new_error (task, G_IO_ERROR, G_IO_ERROR_FAILED, "Internal Error");
536 }
537 else
538 {
539 data = g_new0 (AskQuestionData, 1);
540 data->aborted = aborted;
541 data->choice = choice;
542
543 g_task_return_pointer (task, data, g_free);
544 }
545
546 g_object_unref (task);
547 }
548
549 gboolean
g_mount_source_ask_question(GMountSource * source,const char * message,const char ** choices,gboolean * aborted_out,gint * choice_out)550 g_mount_source_ask_question (GMountSource *source,
551 const char *message,
552 const char **choices,
553 gboolean *aborted_out,
554 gint *choice_out)
555 {
556 gint choice;
557 gboolean handled, aborted;
558 AskSyncData data;
559
560 data.context = g_main_context_new ();
561 data.loop = g_main_loop_new (data.context, FALSE);
562
563 g_main_context_push_thread_default (data.context);
564
565 g_mount_source_ask_question_async (source,
566 message,
567 choices,
568 ask_reply_sync,
569 &data);
570
571 g_main_loop_run (data.loop);
572
573 handled = g_mount_source_ask_question_finish (source,
574 data.result,
575 &aborted,
576 &choice);
577
578 g_main_context_pop_thread_default (data.context);
579 g_main_context_unref (data.context);
580 g_main_loop_unref (data.loop);
581 g_object_unref (data.result);
582
583 if (aborted_out)
584 *aborted_out = aborted;
585
586 if (choice_out)
587 *choice_out = choice;
588
589 return handled;
590 }
591
592 void
g_mount_source_ask_question_async(GMountSource * source,const char * message_string,const char ** choices,GAsyncReadyCallback callback,gpointer user_data)593 g_mount_source_ask_question_async (GMountSource *source,
594 const char *message_string,
595 const char **choices,
596 GAsyncReadyCallback callback,
597 gpointer user_data)
598 {
599 GTask *task;
600 GVfsDBusMountOperation *proxy;
601 GError *error = NULL;
602
603 task = g_task_new (source, NULL, callback, user_data);
604 g_task_set_source_tag (task, g_mount_source_ask_question_async);
605
606 proxy = create_mount_operation_proxy_sync (source, &error);
607 if (proxy == NULL)
608 {
609 g_task_return_error (task, error);
610 g_object_unref (task);
611 return;
612 }
613
614 /* 30 minute timeout */
615 g_dbus_proxy_set_default_timeout (G_DBUS_PROXY (proxy), G_VFS_DBUS_MOUNT_TIMEOUT_MSECS);
616
617 gvfs_dbus_mount_operation_call_ask_question (proxy,
618 message_string ? message_string : "",
619 choices,
620 NULL,
621 (GAsyncReadyCallback) ask_question_reply,
622 task);
623 g_object_unref (proxy);
624 }
625
626 gboolean
g_mount_source_ask_question_finish(GMountSource * source,GAsyncResult * result,gboolean * aborted,gint * choice_out)627 g_mount_source_ask_question_finish (GMountSource *source,
628 GAsyncResult *result,
629 gboolean *aborted,
630 gint *choice_out)
631 {
632 AskQuestionData *data, def = { TRUE, };
633
634 g_return_val_if_fail (g_task_is_valid (result, source), FALSE);
635 g_return_val_if_fail (g_async_result_is_tagged (result, g_mount_source_ask_question_async), FALSE);
636
637 data = g_task_propagate_pointer (G_TASK (result), NULL);
638 if (data == NULL)
639 data = &def;
640
641 if (aborted)
642 *aborted = data->aborted;
643
644 if (choice_out)
645 *choice_out = data->choice;
646
647 return data != &def;
648 }
649
650 static void
op_ask_question_reply(GObject * source_object,GAsyncResult * res,gpointer user_data)651 op_ask_question_reply (GObject *source_object,
652 GAsyncResult *res,
653 gpointer user_data)
654 {
655 GMountOperationResult result;
656 GMountOperation *op;
657 GMountSource *source;
658 gboolean handled, aborted;
659 gint choice;
660
661 source = G_MOUNT_SOURCE (source_object);
662 op = G_MOUNT_OPERATION (user_data);
663
664 handled = g_mount_source_ask_question_finish (source,
665 res,
666 &aborted,
667 &choice);
668
669 if (!handled)
670 result = G_MOUNT_OPERATION_UNHANDLED;
671 else if (aborted)
672 result = G_MOUNT_OPERATION_ABORTED;
673 else
674 {
675 result = G_MOUNT_OPERATION_HANDLED;
676 g_mount_operation_set_choice (op, choice);
677 }
678
679 g_mount_operation_reply (op, result);
680 g_object_unref (op);
681 }
682
683 static gboolean
op_ask_question(GMountOperation * op,const char * message,const char ** choices,GMountSource * mount_source)684 op_ask_question (GMountOperation *op,
685 const char *message,
686 const char **choices,
687 GMountSource *mount_source)
688 {
689 g_mount_source_ask_question_async (mount_source,
690 message,
691 choices,
692 op_ask_question_reply,
693 g_object_ref (op));
694 g_signal_stop_emission_by_name (op, "ask_question");
695 return TRUE;
696 }
697
698 typedef struct ShowProcessesData ShowProcessesData;
699
700 struct ShowProcessesData {
701
702 /* results: */
703 gboolean aborted;
704 guint32 choice;
705 };
706
707 /* the callback from dbus -> main thread */
708 static void
show_processes_reply(GVfsDBusMountOperation * proxy,GAsyncResult * res,gpointer user_data)709 show_processes_reply (GVfsDBusMountOperation *proxy,
710 GAsyncResult *res,
711 gpointer user_data)
712 {
713 GTask *task;
714 ShowProcessesData *data;
715 gboolean handled, aborted;
716 guint32 choice;
717 GError *error;
718
719 task = G_TASK (user_data);
720 handled = TRUE;
721
722 error = NULL;
723 if (!gvfs_dbus_mount_operation_call_show_processes_finish (proxy,
724 &handled,
725 &aborted,
726 &choice,
727 res,
728 &error))
729 {
730 g_dbus_error_strip_remote_error (error);
731 g_task_return_error (task, error);
732 }
733 else if (handled == FALSE)
734 {
735 g_task_return_new_error (task, G_IO_ERROR, G_IO_ERROR_FAILED, "Internal Error");
736 }
737 else
738 {
739 data = g_new0 (ShowProcessesData, 1);
740 data->aborted = aborted;
741 data->choice = choice;
742
743 g_task_return_pointer (task, data, g_free);
744 }
745
746 g_object_unref (task);
747 }
748
749 void
g_mount_source_show_processes_async(GMountSource * source,const char * message_string,GArray * processes,const char ** choices,GAsyncReadyCallback callback,gpointer user_data)750 g_mount_source_show_processes_async (GMountSource *source,
751 const char *message_string,
752 GArray *processes,
753 const char **choices,
754 GAsyncReadyCallback callback,
755 gpointer user_data)
756 {
757 GTask *task;
758 GVfsDBusMountOperation *proxy;
759 GVariantBuilder builder;
760 guint i;
761 GError *error = NULL;
762
763 task = g_task_new (source, NULL, callback, user_data);
764 g_task_set_source_tag (task, g_mount_source_show_processes_async);
765
766 proxy = create_mount_operation_proxy_sync (source, &error);
767 if (proxy == NULL)
768 {
769 g_task_return_error (task, error);
770 g_object_unref (task);
771 return;
772 }
773
774 /* 30 minute timeout */
775 g_dbus_proxy_set_default_timeout (G_DBUS_PROXY (proxy), G_VFS_DBUS_MOUNT_TIMEOUT_MSECS);
776
777 g_variant_builder_init (&builder, G_VARIANT_TYPE ("ai"));
778 for (i = 0; i < processes->len; i++)
779 g_variant_builder_add (&builder, "i",
780 g_array_index (processes, gint32, i));
781
782 gvfs_dbus_mount_operation_call_show_processes (proxy,
783 message_string ? message_string : "",
784 choices,
785 g_variant_builder_end (&builder),
786 NULL,
787 (GAsyncReadyCallback) show_processes_reply,
788 task);
789 g_object_unref (proxy);
790 }
791
792 gboolean
g_mount_source_show_processes_finish(GMountSource * source,GAsyncResult * result,gboolean * aborted,gint * choice_out)793 g_mount_source_show_processes_finish (GMountSource *source,
794 GAsyncResult *result,
795 gboolean *aborted,
796 gint *choice_out)
797 {
798 ShowProcessesData *data, def = { TRUE, };
799
800 g_return_val_if_fail (g_task_is_valid (result, source), FALSE);
801 g_return_val_if_fail (g_async_result_is_tagged (result, g_mount_source_show_processes_async), FALSE);
802
803 data = g_task_propagate_pointer (G_TASK (result), NULL);
804 if (data == NULL)
805 data = &def;
806
807 if (aborted)
808 *aborted = data->aborted;
809
810 if (choice_out)
811 *choice_out = data->choice;
812
813 return data != &def;
814 }
815
816 gboolean
g_mount_source_show_processes(GMountSource * source,const char * message,GArray * processes,const char ** choices,gboolean * aborted_out,gint * choice_out)817 g_mount_source_show_processes (GMountSource *source,
818 const char *message,
819 GArray *processes,
820 const char **choices,
821 gboolean *aborted_out,
822 gint *choice_out)
823 {
824 gint choice;
825 gboolean handled, aborted;
826 AskSyncData data;
827
828 data.context = g_main_context_new ();
829 data.loop = g_main_loop_new (data.context, FALSE);
830
831 g_main_context_push_thread_default (data.context);
832
833 g_mount_source_show_processes_async (source,
834 message,
835 processes,
836 choices,
837 ask_reply_sync,
838 &data);
839
840 g_main_loop_run (data.loop);
841
842 handled = g_mount_source_show_processes_finish (source,
843 data.result,
844 &aborted,
845 &choice);
846
847 g_main_context_pop_thread_default (data.context);
848 g_main_context_unref (data.context);
849 g_main_loop_unref (data.loop);
850 g_object_unref (data.result);
851
852 if (aborted_out)
853 *aborted_out = aborted;
854
855 if (choice_out)
856 *choice_out = choice;
857
858 return handled;
859 }
860
861 static void
op_show_processes_reply(GObject * source_object,GAsyncResult * res,gpointer user_data)862 op_show_processes_reply (GObject *source_object,
863 GAsyncResult *res,
864 gpointer user_data)
865 {
866 GMountOperationResult result;
867 GMountOperation *op;
868 GMountSource *source;
869 gboolean handled, aborted;
870 gint choice;
871
872 source = G_MOUNT_SOURCE (source_object);
873 op = G_MOUNT_OPERATION (user_data);
874
875 handled = g_mount_source_show_processes_finish (source,
876 res,
877 &aborted,
878 &choice);
879
880 if (!handled)
881 result = G_MOUNT_OPERATION_UNHANDLED;
882 else if (aborted)
883 result = G_MOUNT_OPERATION_ABORTED;
884 else
885 {
886 result = G_MOUNT_OPERATION_HANDLED;
887 g_mount_operation_set_choice (op, choice);
888 }
889
890 g_mount_operation_reply (op, result);
891 g_object_unref (op);
892 }
893
894 static gboolean
op_show_processes(GMountOperation * op,const char * message,GArray * processes,const char ** choices,GMountSource * mount_source)895 op_show_processes (GMountOperation *op,
896 const char *message,
897 GArray *processes,
898 const char **choices,
899 GMountSource *mount_source)
900 {
901 g_mount_source_show_processes_async (mount_source,
902 message,
903 processes,
904 choices,
905 op_show_processes_reply,
906 g_object_ref (op));
907 g_signal_stop_emission_by_name (op, "show_processes");
908 return TRUE;
909 }
910
911 static void
show_unmount_progress_reply(GVfsDBusMountOperation * proxy,GAsyncResult * res,gpointer user_data)912 show_unmount_progress_reply (GVfsDBusMountOperation *proxy,
913 GAsyncResult *res,
914 gpointer user_data)
915 {
916 GError *error;
917
918 error = NULL;
919 if (!gvfs_dbus_mount_operation_call_show_unmount_progress_finish (proxy, res, &error))
920 {
921 g_warning ("ShowUnmountProgress request failed: %s", error->message);
922 g_error_free (error);
923 }
924 }
925
926 void
g_mount_source_show_unmount_progress(GMountSource * source,const char * message_string,gint64 time_left,gint64 bytes_left)927 g_mount_source_show_unmount_progress (GMountSource *source,
928 const char *message_string,
929 gint64 time_left,
930 gint64 bytes_left)
931 {
932 GVfsDBusMountOperation *proxy;
933
934 /* If no dbus id specified, warn and return */
935 if (source->dbus_id[0] == 0)
936 {
937 g_warning ("No dbus id specified in the mount source, "
938 "ignoring show-unmount-progress request");
939 return;
940 }
941
942 proxy = create_mount_operation_proxy_sync (source, NULL);
943 if (proxy == NULL)
944 return;
945
946 /* 30 minute timeout */
947 g_dbus_proxy_set_default_timeout (G_DBUS_PROXY (proxy), G_VFS_DBUS_MOUNT_TIMEOUT_MSECS);
948
949 gvfs_dbus_mount_operation_call_show_unmount_progress (proxy,
950 message_string ? message_string : "",
951 time_left,
952 bytes_left,
953 NULL,
954 (GAsyncReadyCallback) show_unmount_progress_reply,
955 NULL);
956 g_object_unref (proxy);
957 }
958
959 static void
op_show_unmount_progress(GMountOperation * op,const char * message,gint64 time_left,gint64 bytes_left,GMountSource * mount_source)960 op_show_unmount_progress (GMountOperation *op,
961 const char *message,
962 gint64 time_left,
963 gint64 bytes_left,
964 GMountSource *mount_source)
965 {
966 g_mount_source_show_unmount_progress (mount_source,
967 message,
968 time_left,
969 bytes_left);
970 g_signal_stop_emission_by_name (op, "show_unmount_progress");
971 }
972
973 static void
abort_reply(GVfsDBusMountOperation * proxy,GAsyncResult * res,gpointer user_data)974 abort_reply (GVfsDBusMountOperation *proxy,
975 GAsyncResult *res,
976 gpointer user_data)
977 {
978 gvfs_dbus_mount_operation_call_aborted_finish (proxy, res, NULL);
979 }
980
981 gboolean
g_mount_source_abort(GMountSource * source)982 g_mount_source_abort (GMountSource *source)
983 {
984 GVfsDBusMountOperation *proxy;
985
986 proxy = create_mount_operation_proxy_sync (source, NULL);
987 if (proxy == NULL)
988 return FALSE;
989
990 gvfs_dbus_mount_operation_call_aborted (proxy, NULL,
991 (GAsyncReadyCallback) abort_reply, NULL);
992
993 g_object_unref (proxy);
994 return TRUE;
995 }
996
997 static void
op_aborted(GMountOperation * op,GMountSource * source)998 op_aborted (GMountOperation *op,
999 GMountSource *source)
1000 {
1001 g_mount_source_abort (source);
1002 }
1003
1004 gboolean
g_mount_source_is_dummy(GMountSource * source)1005 g_mount_source_is_dummy (GMountSource *source)
1006 {
1007 g_return_val_if_fail (G_IS_MOUNT_SOURCE (source), TRUE);
1008 return source->dbus_id[0] == 0;
1009 }
1010
1011
1012 GMountOperation *
g_mount_source_get_operation(GMountSource * mount_source)1013 g_mount_source_get_operation (GMountSource *mount_source)
1014 {
1015 GMountOperation *op;
1016
1017 op = g_mount_operation_new ();
1018 g_object_set_data_full (G_OBJECT (op), "source",
1019 g_object_ref (mount_source),
1020 g_object_unref);
1021
1022 g_signal_connect (op, "ask_password", (GCallback)op_ask_password, mount_source);
1023 g_signal_connect (op, "ask_question", (GCallback)op_ask_question, mount_source);
1024 g_signal_connect (op, "show_processes", (GCallback)op_show_processes, mount_source);
1025 g_signal_connect (op, "show_unmount_progress", (GCallback)op_show_unmount_progress, mount_source);
1026 g_signal_connect (op, "aborted", (GCallback)op_aborted, mount_source);
1027
1028 return op;
1029 }
1030