~ctf/unity-settings-daemon/bug1389099_mic_volume_icons

« back to all changes in this revision

Viewing changes to plugins/automount/gsd-automount-manager.c

  • Committer: Package Import Robot
  • Author(s): Robert Ancell
  • Date: 2014-02-07 11:44:36 UTC
  • Revision ID: package-import@ubuntu.com-20140207114436-7t5u3yvwc4ul7w3e
Tags: upstream-14.04.0
ImportĀ upstreamĀ versionĀ 14.04.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
 
2
 *
 
3
 * Copyright (C) 2010 Red Hat, Inc.
 
4
 *
 
5
 * This program is free software; you can redistribute it and/or modify
 
6
 * it under the terms of the GNU General Public License as published by
 
7
 * the Free Software Foundation; either version 2 of the License, or
 
8
 * (at your option) any later version.
 
9
 *
 
10
 * This program 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
 
13
 * GNU General Public License for more details.
 
14
 *
 
15
 * You should have received a copy of the GNU General Public License
 
16
 * along with this program; if not, write to the Free Software
 
17
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 
18
 *
 
19
 * Author: Tomas Bzatek <tbzatek@redhat.com>
 
20
 */
 
21
 
 
22
#include "config.h"
 
23
 
 
24
#include <stdlib.h>
 
25
#include <string.h>
 
26
 
 
27
#include <glib.h>
 
28
#include <glib/gi18n.h>
 
29
#include <gio/gio.h>
 
30
 
 
31
#include "gnome-settings-profile.h"
 
32
#include "gnome-settings-session.h"
 
33
#include "gsd-automount-manager.h"
 
34
#include "gsd-autorun.h"
 
35
 
 
36
#define GSD_AUTOMOUNT_MANAGER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GSD_TYPE_AUTOMOUNT_MANAGER, GsdAutomountManagerPrivate))
 
37
 
 
38
struct GsdAutomountManagerPrivate
 
39
{
 
40
        GSettings   *settings;
 
41
 
 
42
        GVolumeMonitor *volume_monitor;
 
43
        unsigned int automount_idle_id;
 
44
 
 
45
        GDBusProxy *session;
 
46
        gboolean session_is_active;
 
47
        gboolean screensaver_active;
 
48
        guint ss_watch_id;
 
49
        GDBusProxy *ss_proxy;
 
50
 
 
51
        GList *volume_queue;
 
52
};
 
53
 
 
54
static void     gsd_automount_manager_class_init  (GsdAutomountManagerClass *klass);
 
55
static void     gsd_automount_manager_init        (GsdAutomountManager      *gsd_automount_manager);
 
56
 
 
57
G_DEFINE_TYPE (GsdAutomountManager, gsd_automount_manager, G_TYPE_OBJECT)
 
58
 
 
59
static GtkDialog *
 
60
show_error_dialog (const char *primary_text,
 
61
                   const char *secondary_text)
 
62
{
 
63
        GtkWidget *dialog;
 
64
 
 
65
        dialog = gtk_message_dialog_new (NULL,
 
66
                                         0,
 
67
                                         GTK_MESSAGE_ERROR,
 
68
                                         GTK_BUTTONS_OK,
 
69
                                         "%s", "");
 
70
 
 
71
        g_object_set (dialog,
 
72
                      "text", primary_text,
 
73
                      "secondary-text", secondary_text,
 
74
                      NULL);
 
75
 
 
76
        gtk_widget_show (GTK_WIDGET (dialog));
 
77
 
 
78
        g_signal_connect (dialog, "response",
 
79
                          G_CALLBACK (gtk_widget_destroy), NULL);
 
80
 
 
81
        gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK);
 
82
 
 
83
        return GTK_DIALOG (dialog);
 
84
}
 
85
 
 
86
static void
 
87
startup_volume_mount_cb (GObject *source_object,
 
88
                         GAsyncResult *res,
 
89
                         gpointer user_data)
 
90
{
 
91
        g_volume_mount_finish (G_VOLUME (source_object), res, NULL);
 
92
}
 
93
 
 
94
static void
 
95
automount_all_volumes (GsdAutomountManager *manager)
 
96
{
 
97
        GList *volumes, *l;
 
98
        GMount *mount;
 
99
        GVolume *volume;
 
100
 
 
101
        if (g_settings_get_boolean (manager->priv->settings, "automount")) {
 
102
                /* automount all mountable volumes at start-up */
 
103
                volumes = g_volume_monitor_get_volumes (manager->priv->volume_monitor);
 
104
                for (l = volumes; l != NULL; l = l->next) {
 
105
                        volume = l->data;
 
106
 
 
107
                        if (!g_volume_should_automount (volume) ||
 
108
                            !g_volume_can_mount (volume)) {
 
109
                                continue;
 
110
                        }
 
111
 
 
112
                        mount = g_volume_get_mount (volume);
 
113
                        if (mount != NULL) {
 
114
                                g_object_unref (mount);
 
115
                                continue;
 
116
                        }
 
117
 
 
118
                        /* pass NULL as GMountOperation to avoid user interaction */
 
119
                        g_volume_mount (volume, 0, NULL, NULL, startup_volume_mount_cb, NULL);
 
120
                }
 
121
                g_list_free_full (volumes, g_object_unref);
 
122
        }
 
123
}
 
124
 
 
125
static gboolean
 
126
automount_all_volumes_idle_cb (gpointer data)
 
127
{
 
128
        GsdAutomountManager *manager = GSD_AUTOMOUNT_MANAGER (data);
 
129
 
 
130
        automount_all_volumes (manager);
 
131
 
 
132
        manager->priv->automount_idle_id = 0;
 
133
        return FALSE;
 
134
}
 
135
 
 
136
static void
 
137
volume_mount_cb (GObject *source_object,
 
138
                 GAsyncResult *res,
 
139
                 gpointer user_data)
 
140
{
 
141
        GMountOperation *mount_op = user_data;
 
142
        GError *error;
 
143
        char *primary;
 
144
        char *name;
 
145
 
 
146
        error = NULL;
 
147
        gsd_allow_autorun_for_volume_finish (G_VOLUME (source_object));
 
148
        if (!g_volume_mount_finish (G_VOLUME (source_object), res, &error)) {
 
149
                if (error->code != G_IO_ERROR_FAILED_HANDLED) {
 
150
                        name = g_volume_get_name (G_VOLUME (source_object));
 
151
                        primary = g_strdup_printf (_("Unable to mount %s"), name);
 
152
                        g_free (name);
 
153
                        show_error_dialog (primary,
 
154
                                           error->message);
 
155
                        g_free (primary);
 
156
                }
 
157
                g_error_free (error);
 
158
        }
 
159
 
 
160
        g_object_unref (mount_op);
 
161
}
 
162
 
 
163
static void
 
164
do_mount_volume (GVolume *volume)
 
165
{
 
166
        GMountOperation *mount_op;
 
167
 
 
168
        mount_op = gtk_mount_operation_new (NULL);
 
169
        g_mount_operation_set_password_save (mount_op, G_PASSWORD_SAVE_FOR_SESSION);
 
170
 
 
171
        gsd_allow_autorun_for_volume (volume);
 
172
        g_volume_mount (volume, 0, mount_op, NULL, volume_mount_cb, mount_op);
 
173
}
 
174
 
 
175
static void
 
176
check_volume_queue (GsdAutomountManager *manager)
 
177
{
 
178
        GList *l;
 
179
        GVolume *volume;
 
180
 
 
181
        if (manager->priv->screensaver_active)
 
182
                return;
 
183
 
 
184
        l = manager->priv->volume_queue;
 
185
 
 
186
        while (l != NULL) {
 
187
                volume = l->data;
 
188
 
 
189
                do_mount_volume (volume);
 
190
                manager->priv->volume_queue =
 
191
                        g_list_remove (manager->priv->volume_queue, volume);
 
192
 
 
193
                g_object_unref (volume);
 
194
                l = l->next;
 
195
        }
 
196
 
 
197
        manager->priv->volume_queue = NULL;
 
198
}
 
199
 
 
200
static void
 
201
check_screen_lock_and_mount (GsdAutomountManager *manager,
 
202
                             GVolume *volume)
 
203
{
 
204
        if (!manager->priv->session_is_active)
 
205
                return;
 
206
 
 
207
        if (manager->priv->screensaver_active) {
 
208
                /* queue the volume, to mount it after the screensaver state changed */
 
209
                g_debug ("Queuing volume %p", volume);
 
210
                manager->priv->volume_queue = g_list_prepend (manager->priv->volume_queue,
 
211
                                                              g_object_ref (volume));
 
212
        } else {
 
213
                /* mount it immediately */
 
214
                do_mount_volume (volume);
 
215
        }
 
216
}
 
217
 
 
218
static void
 
219
volume_removed_callback (GVolumeMonitor *monitor,
 
220
                         GVolume *volume,
 
221
                         GsdAutomountManager *manager)
 
222
{
 
223
        g_debug ("Volume %p removed, removing from the queue", volume);
 
224
 
 
225
        /* clear it from the queue, if present */
 
226
        manager->priv->volume_queue =
 
227
                g_list_remove (manager->priv->volume_queue, volume);
 
228
}
 
229
 
 
230
static void
 
231
volume_added_callback (GVolumeMonitor *monitor,
 
232
                       GVolume *volume,
 
233
                       GsdAutomountManager *manager)
 
234
{
 
235
        if (g_settings_get_boolean (manager->priv->settings, "automount") &&
 
236
            g_volume_should_automount (volume) &&
 
237
            g_volume_can_mount (volume)) {
 
238
                check_screen_lock_and_mount (manager, volume);
 
239
        } else {
 
240
                /* Allow gsd_autorun() to run. When the mount is later
 
241
                 * added programmatically (i.e. for a blank CD),
 
242
                 * gsd_autorun() will be called by mount_added_callback(). */
 
243
                gsd_allow_autorun_for_volume (volume);
 
244
                gsd_allow_autorun_for_volume_finish (volume);
 
245
        }
 
246
}
 
247
 
 
248
static void
 
249
autorun_show_window (GMount *mount, gpointer user_data)
 
250
{
 
251
        GFile *location;
 
252
        char *uri;
 
253
        GError *error;
 
254
        char *primary;
 
255
        char *name;
 
256
 
 
257
        location = g_mount_get_root (mount);
 
258
        uri = g_file_get_uri (location);
 
259
 
 
260
        error = NULL;
 
261
        /* use default folder handler */
 
262
        if (! gtk_show_uri (NULL, uri, GDK_CURRENT_TIME, &error)) {
 
263
                name = g_mount_get_name (mount);
 
264
                primary = g_strdup_printf (_("Unable to open a folder for %s"), name);
 
265
                g_free (name);
 
266
                show_error_dialog (primary,
 
267
                                   error->message);
 
268
                g_free (primary);
 
269
                g_error_free (error);
 
270
        }
 
271
 
 
272
        g_free (uri);
 
273
        g_object_unref (location);
 
274
}
 
275
 
 
276
static void
 
277
mount_added_callback (GVolumeMonitor *monitor,
 
278
                      GMount *mount,
 
279
                      GsdAutomountManager *manager)
 
280
{
 
281
        /* don't autorun if the session is not active */
 
282
        if (!manager->priv->session_is_active) {
 
283
                return;
 
284
        }
 
285
 
 
286
        gsd_autorun (mount, manager->priv->settings, autorun_show_window, manager);
 
287
}
 
288
 
 
289
 
 
290
static void
 
291
session_state_changed (GDBusProxy      *session,
 
292
                       GVariant        *changed,
 
293
                       char           **invalidated,
 
294
                       GsdAutomountManager *manager)
 
295
{
 
296
        GsdAutomountManagerPrivate *p = manager->priv;
 
297
 
 
298
        GVariant *v;
 
299
 
 
300
        v = g_variant_lookup_value (changed, "SessionIsActive", G_VARIANT_TYPE_BOOLEAN);
 
301
 
 
302
        if (v) {
 
303
                gboolean active;
 
304
 
 
305
                active = g_variant_get_boolean (v);
 
306
                g_debug ("Received session is active change: now %s", active ? "active" : "inactive");
 
307
                /* when doing the fast-user-switch into a new account,
 
308
                 * ensure the new account is undimmed and with the backlight on */
 
309
                if (active)
 
310
                        p->session_is_active = TRUE;
 
311
                else
 
312
                        p->session_is_active = FALSE;
 
313
 
 
314
                g_variant_unref (v);
 
315
 
 
316
        }
 
317
 
 
318
        if (!p->session_is_active) {
 
319
                if (p->volume_queue != NULL) {
 
320
                        g_list_free_full (p->volume_queue, g_object_unref);
 
321
                        p->volume_queue = NULL;
 
322
                }
 
323
        }
 
324
}
 
325
 
 
326
static gboolean
 
327
is_session_active (GsdAutomountManager *manager)
 
328
{
 
329
        GVariant *variant;
 
330
        gboolean is_session_active = FALSE;
 
331
 
 
332
        variant = g_dbus_proxy_get_cached_property (manager->priv->session,
 
333
                                                    "SessionIsActive");
 
334
        if (variant) {
 
335
                is_session_active = g_variant_get_boolean (variant);
 
336
                g_variant_unref (variant);
 
337
        }
 
338
 
 
339
        return is_session_active;
 
340
}
 
341
 
 
342
 
 
343
static void
 
344
do_initialize_session (GsdAutomountManager *manager)
 
345
{
 
346
        manager->priv->session = gnome_settings_session_get_session_proxy ();
 
347
        g_signal_connect (manager->priv->session, "g-properties-changed",
 
348
                          G_CALLBACK (session_state_changed),
 
349
                          manager);
 
350
        manager->priv->session_is_active = is_session_active (manager);
 
351
}
 
352
 
 
353
#define SCREENSAVER_NAME "org.gnome.ScreenSaver"
 
354
#define SCREENSAVER_PATH "/org/gnome/ScreenSaver"
 
355
#define SCREENSAVER_INTERFACE "org.gnome.ScreenSaver"
 
356
 
 
357
static void
 
358
screensaver_signal_callback (GDBusProxy *proxy,
 
359
                             const gchar *sender_name,
 
360
                             const gchar *signal_name,
 
361
                             GVariant *parameters,
 
362
                             gpointer user_data)
 
363
{
 
364
        GsdAutomountManager *manager = user_data;
 
365
 
 
366
        if (g_strcmp0 (signal_name, "ActiveChanged") == 0) {
 
367
                g_variant_get (parameters, "(b)", &manager->priv->screensaver_active);
 
368
                g_debug ("Screensaver active changed to %d", manager->priv->screensaver_active);
 
369
 
 
370
                check_volume_queue (manager);
 
371
        }
 
372
}
 
373
 
 
374
static void
 
375
screensaver_get_active_ready_cb (GObject *source,
 
376
                                 GAsyncResult *res,
 
377
                                 gpointer user_data)
 
378
{
 
379
        GsdAutomountManager *manager = user_data;
 
380
        GDBusProxy *proxy = manager->priv->ss_proxy;
 
381
        GVariant *result;
 
382
        GError *error = NULL;
 
383
 
 
384
        result = g_dbus_proxy_call_finish (proxy,
 
385
                                           res,
 
386
                                           &error);
 
387
 
 
388
        if (error != NULL) {
 
389
                g_warning ("Can't call GetActive() on the ScreenSaver object: %s",
 
390
                           error->message);
 
391
                g_error_free (error);
 
392
 
 
393
                return;
 
394
        }
 
395
 
 
396
        g_variant_get (result, "(b)", &manager->priv->screensaver_active);
 
397
        g_variant_unref (result);
 
398
 
 
399
        g_debug ("Screensaver GetActive() returned %d", manager->priv->screensaver_active);
 
400
}
 
401
 
 
402
static void
 
403
screensaver_proxy_ready_cb (GObject *source,
 
404
                            GAsyncResult *res,
 
405
                            gpointer user_data)
 
406
{
 
407
        GsdAutomountManager *manager = user_data;
 
408
        GError *error = NULL;
 
409
        GDBusProxy *ss_proxy;
 
410
 
 
411
        ss_proxy = g_dbus_proxy_new_finish (res, &error);
 
412
 
 
413
        if (error != NULL) {
 
414
                g_warning ("Can't get proxy for the ScreenSaver object: %s",
 
415
                           error->message);
 
416
                g_error_free (error);
 
417
 
 
418
                return;
 
419
        }
 
420
 
 
421
        g_debug ("ScreenSaver proxy ready");
 
422
 
 
423
        manager->priv->ss_proxy = ss_proxy;
 
424
 
 
425
        g_signal_connect (ss_proxy, "g-signal",
 
426
                          G_CALLBACK (screensaver_signal_callback), manager);
 
427
 
 
428
        g_dbus_proxy_call (ss_proxy,
 
429
                           "GetActive",
 
430
                           NULL,
 
431
                           G_DBUS_CALL_FLAGS_NO_AUTO_START,
 
432
                           -1,
 
433
                           NULL,
 
434
                           screensaver_get_active_ready_cb,
 
435
                           manager);
 
436
}
 
437
 
 
438
static void
 
439
screensaver_appeared_callback (GDBusConnection *connection,
 
440
                               const gchar *name,
 
441
                               const gchar *name_owner,
 
442
                               gpointer user_data)
 
443
{
 
444
        GsdAutomountManager *manager = user_data;
 
445
 
 
446
        g_debug ("ScreenSaver name appeared");
 
447
 
 
448
        manager->priv->screensaver_active = FALSE;
 
449
 
 
450
        g_dbus_proxy_new (connection,
 
451
                          G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START,
 
452
                          NULL,
 
453
                          name,
 
454
                          SCREENSAVER_PATH,
 
455
                          SCREENSAVER_INTERFACE,
 
456
                          NULL,
 
457
                          screensaver_proxy_ready_cb,
 
458
                          manager);
 
459
}
 
460
 
 
461
static void
 
462
screensaver_vanished_callback (GDBusConnection *connection,
 
463
                               const gchar *name,
 
464
                               gpointer user_data)
 
465
{
 
466
        GsdAutomountManager *manager = user_data;
 
467
 
 
468
        g_debug ("ScreenSaver name vanished");
 
469
 
 
470
        manager->priv->screensaver_active = FALSE;
 
471
        g_clear_object (&manager->priv->ss_proxy);
 
472
 
 
473
        /* in this case force a clear of the volume queue, without
 
474
         * mounting them.
 
475
         */
 
476
        if (manager->priv->volume_queue != NULL) {
 
477
                g_list_free_full (manager->priv->volume_queue, g_object_unref);
 
478
                manager->priv->volume_queue = NULL;
 
479
        }
 
480
}
 
481
 
 
482
static void
 
483
do_initialize_screensaver (GsdAutomountManager *manager)
 
484
{
 
485
        GsdAutomountManagerPrivate *p = manager->priv;
 
486
 
 
487
        p->ss_watch_id =
 
488
                g_bus_watch_name (G_BUS_TYPE_SESSION,
 
489
                                  SCREENSAVER_NAME,
 
490
                                  G_BUS_NAME_WATCHER_FLAGS_NONE,
 
491
                                  screensaver_appeared_callback,
 
492
                                  screensaver_vanished_callback,
 
493
                                  manager,
 
494
                                  NULL);
 
495
}
 
496
 
 
497
static void
 
498
setup_automounter (GsdAutomountManager *manager)
 
499
{
 
500
        do_initialize_session (manager);
 
501
        do_initialize_screensaver (manager);
 
502
 
 
503
        manager->priv->volume_monitor = g_volume_monitor_get ();
 
504
        g_signal_connect_object (manager->priv->volume_monitor, "mount-added",
 
505
                                 G_CALLBACK (mount_added_callback), manager, 0);
 
506
        g_signal_connect_object (manager->priv->volume_monitor, "volume-added",
 
507
                                 G_CALLBACK (volume_added_callback), manager, 0);
 
508
        g_signal_connect_object (manager->priv->volume_monitor, "volume-removed",
 
509
                                 G_CALLBACK (volume_removed_callback), manager, 0);
 
510
 
 
511
        manager->priv->automount_idle_id =
 
512
                g_idle_add_full (G_PRIORITY_LOW,
 
513
                                 automount_all_volumes_idle_cb,
 
514
                                 manager, NULL);
 
515
}
 
516
 
 
517
gboolean
 
518
gsd_automount_manager_start (GsdAutomountManager *manager,
 
519
                                       GError              **error)
 
520
{
 
521
        g_debug ("Starting automounting manager");
 
522
        gnome_settings_profile_start (NULL);
 
523
 
 
524
        manager->priv->settings = g_settings_new ("org.gnome.desktop.media-handling");
 
525
        setup_automounter (manager);
 
526
 
 
527
        gnome_settings_profile_end (NULL);
 
528
 
 
529
        return TRUE;
 
530
}
 
531
 
 
532
void
 
533
gsd_automount_manager_stop (GsdAutomountManager *manager)
 
534
{
 
535
        GsdAutomountManagerPrivate *p = manager->priv;
 
536
 
 
537
        g_debug ("Stopping automounting manager");
 
538
 
 
539
        g_clear_object (&p->session);
 
540
        g_clear_object (&p->volume_monitor);
 
541
        g_clear_object (&p->settings);
 
542
        g_clear_object (&p->ss_proxy);
 
543
 
 
544
        g_bus_unwatch_name (p->ss_watch_id);
 
545
 
 
546
        if (p->volume_queue != NULL) {
 
547
                g_list_free_full (p->volume_queue, g_object_unref);
 
548
                p->volume_queue = NULL;
 
549
        }
 
550
 
 
551
        if (p->automount_idle_id != 0) {
 
552
                g_source_remove (p->automount_idle_id);
 
553
                p->automount_idle_id = 0;
 
554
        }
 
555
}
 
556
 
 
557
static void
 
558
gsd_automount_manager_class_init (GsdAutomountManagerClass *klass)
 
559
{
 
560
        g_type_class_add_private (klass, sizeof (GsdAutomountManagerPrivate));
 
561
}
 
562
 
 
563
static void
 
564
gsd_automount_manager_init (GsdAutomountManager *manager)
 
565
{
 
566
        manager->priv = GSD_AUTOMOUNT_MANAGER_GET_PRIVATE (manager);
 
567
}
 
568
 
 
569
GsdAutomountManager *
 
570
gsd_automount_manager_new (void)
 
571
{
 
572
        return GSD_AUTOMOUNT_MANAGER (g_object_new (GSD_TYPE_AUTOMOUNT_MANAGER, NULL));
 
573
}