~ubuntu-branches/ubuntu/oneiric/evince/oneiric-updates

« back to all changes in this revision

Viewing changes to shell/ev-daemon.c

  • Committer: Bazaar Package Importer
  • Author(s): Frederic Peters
  • Date: 2011-04-14 16:20:57 UTC
  • mfrom: (1.6.4 upstream)
  • mto: (1.3.5 experimental)
  • mto: This revision was merged to the branch mainline in revision 138.
  • Revision ID: james.westby@ubuntu.com-20110414162057-0ofhbd139zs6ev6y
ImportĀ upstreamĀ versionĀ 3.0.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* ev-metadata.c
 
1
/* ev-daemon.c
2
2
 *  this file is part of evince, a gnome document viewer
3
3
 *
4
4
 * Copyright (C) 2009 Carlos Garcia Campos  <carlosgc@gnome.org>
 
5
 * Copyright Ā© 2010 Christian Persch
5
6
 *
6
7
 * Evince is free software; you can redistribute it and/or modify it
7
8
 * under the terms of the GNU General Public License as published by
15
16
 *
16
17
 * You should have received a copy of the GNU General Public License
17
18
 * along with this program; if not, write to the Free Software
18
 
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
 
19
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19
20
 */
20
21
 
21
22
#include "config.h"
29
30
#include <sys/wait.h>
30
31
#include <fcntl.h>
31
32
#include <unistd.h>
32
 
#include <dbus/dbus-glib-bindings.h>
33
 
#include <dbus/dbus-glib-lowlevel.h>
34
 
 
35
 
#define EV_DBUS_DAEMON_NAME        "org.gnome.evince.Daemon"
36
 
#define EV_DBUS_DAEMON_OBJECT_PATH "/org/gnome/evince/Daemon"
37
 
 
38
 
#define EV_TYPE_DAEMON                     (ev_daemon_get_type ())
39
 
#define EV_DAEMON(object)                  (G_TYPE_CHECK_INSTANCE_CAST((object), EV_TYPE_DAEMON, EvDaemon))
40
 
#define EV_DAEMON_CLASS(klass)             (G_TYPE_CHECK_CLASS_CAST((klass), EV_TYPE_DAEMON, EvDaemonClass))
41
 
#define EV_IS_DAEMON(object)               (G_TYPE_CHECK_INSTANCE_TYPE((object), EV_TYPE_DAEMON))
42
 
 
43
 
typedef struct _EvDaemon      EvDaemon;
44
 
typedef struct _EvDaemonClass EvDaemonClass;
45
 
 
46
 
struct _EvDaemon {
47
 
        GObject base;
48
 
 
49
 
        DBusGProxy *bus_proxy;
50
 
 
51
 
        GList      *docs;
52
 
        guint       n_docs;
53
 
 
54
 
        guint       timer_id;
55
 
};
56
 
 
57
 
struct _EvDaemonClass {
58
 
        GObjectClass base_class;
59
 
};
60
 
 
61
 
static GType    ev_daemon_get_type            (void) G_GNUC_CONST;
62
 
static gboolean ev_daemon_register_document   (EvDaemon              *ev_daemon,
63
 
                                               const gchar           *uri,
64
 
                                               DBusGMethodInvocation *context);
65
 
static gboolean ev_daemon_unregister_document (EvDaemon              *ev_daemon,
66
 
                                               const gchar           *uri,
67
 
                                               DBusGMethodInvocation *context);
68
 
#include "ev-daemon-service.h"
69
 
 
70
 
static EvDaemon *ev_daemon = NULL;
71
 
 
72
 
G_DEFINE_TYPE(EvDaemon, ev_daemon, G_TYPE_OBJECT)
 
33
 
 
34
#define EV_DBUS_DAEMON_NAME             "org.gnome.evince.Daemon"
 
35
#define EV_DBUS_DAEMON_INTERFACE_NAME   "org.gnome.evince.Daemon"
 
36
#define EV_DBUS_DAEMON_OBJECT_PATH      "/org/gnome/evince/Daemon"
 
37
 
 
38
#define EV_DBUS_WINDOW_INTERFACE_NAME   "org.gnome.evince.Window"
 
39
 
 
40
#define DAEMON_TIMEOUT (30) /* seconds */
 
41
 
 
42
#define LOG g_printerr
 
43
 
 
44
static GList *ev_daemon_docs = NULL;
 
45
static guint kill_timer_id;
 
46
static GHashTable *pending_invocations = NULL;
73
47
 
74
48
typedef struct {
75
49
        gchar *dbus_name;
76
50
        gchar *uri;
 
51
        guint  watch_id;
 
52
        guint  loaded_id;
77
53
} EvDoc;
78
54
 
79
55
static void
85
61
        g_free (doc->dbus_name);
86
62
        g_free (doc->uri);
87
63
 
 
64
        g_bus_unwatch_name (doc->watch_id);
 
65
 
88
66
        g_free (doc);
89
67
}
90
68
 
91
69
static EvDoc *
92
 
ev_daemon_find_doc (EvDaemon    *ev_daemon,
93
 
                    const gchar *uri)
 
70
ev_daemon_find_doc (const gchar *uri)
94
71
{
95
72
        GList *l;
96
73
 
97
 
        for (l = ev_daemon->docs; l; l = g_list_next (l)) {
 
74
        for (l = ev_daemon_docs; l != NULL; l = l->next) {
98
75
                EvDoc *doc = (EvDoc *)l->data;
99
76
 
100
77
                if (strcmp (doc->uri, uri) == 0)
105
82
}
106
83
 
107
84
static void
108
 
ev_daemon_finalize (GObject *object)
109
 
{
110
 
        EvDaemon *ev_daemon = EV_DAEMON (object);
111
 
 
112
 
        if (ev_daemon->docs) {
113
 
                g_list_foreach (ev_daemon->docs, (GFunc)ev_doc_free, NULL);
114
 
                g_list_free (ev_daemon->docs);
115
 
                ev_daemon->docs = NULL;
116
 
        }
117
 
 
118
 
        if (ev_daemon->bus_proxy) {
119
 
                g_object_unref (ev_daemon->bus_proxy);
120
 
                ev_daemon->bus_proxy = NULL;
121
 
        }
122
 
 
123
 
        G_OBJECT_CLASS (ev_daemon_parent_class)->finalize (object);
124
 
}
125
 
 
126
 
static void
127
 
ev_daemon_init (EvDaemon *ev_daemon)
128
 
{
129
 
}
130
 
 
131
 
static void
132
 
ev_daemon_class_init (EvDaemonClass *klass)
133
 
{
134
 
        GObjectClass *g_object_class = G_OBJECT_CLASS (klass);
135
 
 
136
 
        g_object_class->finalize = ev_daemon_finalize;
137
 
 
138
 
        dbus_g_object_type_install_info (EV_TYPE_DAEMON,
139
 
                                         &dbus_glib_ev_daemon_object_info);
140
 
}
141
 
 
142
 
static gboolean
143
 
ev_daemon_shutdown (EvDaemon *ev_daemon)
144
 
{
145
 
        g_object_unref (ev_daemon);
146
 
 
147
 
        return FALSE;
148
 
}
149
 
 
150
 
static void
151
 
ev_daemon_stop_killtimer (EvDaemon *ev_daemon)
152
 
{
153
 
        if (ev_daemon->timer_id != 0)
154
 
                g_source_remove (ev_daemon->timer_id);
155
 
        ev_daemon->timer_id = 0;
156
 
}
157
 
 
158
 
static void
159
 
ev_daemon_start_killtimer (EvDaemon *ev_daemon)
160
 
{
161
 
        ev_daemon_stop_killtimer (ev_daemon);
162
 
        ev_daemon->timer_id =
163
 
                g_timeout_add_seconds (30,
164
 
                                       (GSourceFunc) ev_daemon_shutdown,
165
 
                                       ev_daemon);
166
 
}
167
 
 
168
 
static void
169
 
ev_daemon_name_owner_changed (DBusGProxy  *proxy,
170
 
                              const gchar *name,
171
 
                              const gchar *old_owner,
172
 
                              const gchar *new_owner,
173
 
                              EvDaemon    *ev_daemon)
174
 
{
175
 
        GList *l, *next = NULL;
176
 
 
177
 
        if (*name == ':' && *new_owner == '\0') {
178
 
                for (l = ev_daemon->docs; l; l = next) {
179
 
                        EvDoc *doc = (EvDoc *)l->data;
180
 
 
181
 
                        next = l->next;
182
 
                        if (strcmp (doc->dbus_name, name) == 0) {
183
 
                                ev_doc_free (doc);
184
 
                                ev_daemon->docs = g_list_delete_link (ev_daemon->docs, l);
185
 
                                if (--ev_daemon->n_docs == 0)
186
 
                                        ev_daemon_start_killtimer (ev_daemon);
187
 
                        }
188
 
                }
189
 
        }
190
 
}
191
 
 
192
 
static EvDaemon *
193
 
ev_daemon_get (void)
194
 
{
195
 
        DBusGConnection *connection;
196
 
        guint            request_name_result;
197
 
        GError          *error = NULL;
198
 
 
199
 
        if (ev_daemon)
200
 
                return ev_daemon;
201
 
 
202
 
        connection = dbus_g_bus_get (DBUS_BUS_STARTER, &error);
203
 
        if (!connection) {
204
 
                g_printerr ("Failed to connect to the D-BUS daemon: %s\n", error->message);
205
 
                g_error_free (error);
206
 
 
207
 
                return NULL;
208
 
        }
209
 
 
210
 
        ev_daemon = g_object_new (EV_TYPE_DAEMON, NULL);
211
 
 
212
 
        ev_daemon->bus_proxy = dbus_g_proxy_new_for_name (connection,
213
 
                                                       DBUS_SERVICE_DBUS,
214
 
                                                       DBUS_PATH_DBUS,
215
 
                                                       DBUS_INTERFACE_DBUS);
216
 
        if (!org_freedesktop_DBus_request_name (ev_daemon->bus_proxy,
217
 
                                                EV_DBUS_DAEMON_NAME,
218
 
                                                DBUS_NAME_FLAG_DO_NOT_QUEUE,
219
 
                                                &request_name_result, &error)) {
220
 
                g_printerr ("Failed to acquire daemon name: %s", error->message);
221
 
                g_error_free (error);
222
 
                g_object_unref (ev_daemon);
223
 
 
224
 
                return NULL;
225
 
        }
226
 
 
227
 
        switch (request_name_result) {
228
 
        case DBUS_REQUEST_NAME_REPLY_EXISTS:
229
 
                g_printerr ("Evince daemon already running, exiting.\n");
230
 
                g_object_unref (ev_daemon);
231
 
 
232
 
                return NULL;
233
 
        case DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER:
234
 
                dbus_g_connection_register_g_object (connection,
235
 
                                                     EV_DBUS_DAEMON_OBJECT_PATH,
236
 
                                                     G_OBJECT (ev_daemon));
237
 
                break;
238
 
        default:
239
 
                g_printerr ("Not primary owner of the service, exiting.\n");
240
 
                g_object_unref (ev_daemon);
241
 
 
242
 
                return NULL;
243
 
        }
244
 
 
245
 
 
246
 
        dbus_g_proxy_add_signal (ev_daemon->bus_proxy,
247
 
                                 "NameOwnerChanged",
248
 
                                 G_TYPE_STRING,
249
 
                                 G_TYPE_STRING,
250
 
                                 G_TYPE_STRING,
251
 
                                 G_TYPE_INVALID);
252
 
        dbus_g_proxy_connect_signal (ev_daemon->bus_proxy, "NameOwnerChanged",
253
 
                                     G_CALLBACK (ev_daemon_name_owner_changed),
254
 
                                     ev_daemon, NULL);
255
 
        ev_daemon_start_killtimer (ev_daemon);
256
 
 
257
 
        return ev_daemon;
258
 
}
259
 
 
260
 
 
261
 
 
262
 
static gboolean
263
 
ev_daemon_register_document (EvDaemon              *ev_daemon,
264
 
                             const gchar           *uri,
265
 
                             DBusGMethodInvocation *method)
266
 
{
267
 
        EvDoc       *doc;
268
 
        const gchar *owner = NULL;
269
 
 
270
 
        doc = ev_daemon_find_doc (ev_daemon, uri);
271
 
        if (doc) {
272
 
                /* Already registered */
273
 
                owner = doc->dbus_name;
274
 
        } else {
275
 
                doc = g_new (EvDoc, 1);
276
 
                doc->dbus_name = dbus_g_method_get_sender (method);
277
 
                doc->uri = g_strdup (uri);
278
 
                ev_daemon->docs = g_list_prepend (ev_daemon->docs, doc);
279
 
                if (ev_daemon->n_docs++ == 0)
280
 
                        ev_daemon_stop_killtimer (ev_daemon);
281
 
        }
282
 
 
283
 
        dbus_g_method_return (method, owner);
284
 
 
285
 
        return TRUE;
286
 
}
287
 
 
288
 
static gboolean
289
 
ev_daemon_unregister_document (EvDaemon              *ev_daemon,
290
 
                               const gchar           *uri,
291
 
                               DBusGMethodInvocation *method)
292
 
{
293
 
        EvDoc *doc;
294
 
        gchar *sender;
295
 
 
296
 
        doc = ev_daemon_find_doc (ev_daemon, uri);
297
 
        if (!doc) {
298
 
                g_warning ("Document %s is not registered\n", uri);
299
 
                dbus_g_method_return (method);
300
 
 
301
 
                return TRUE;
302
 
        }
303
 
 
304
 
        sender = dbus_g_method_get_sender (method);
305
 
        if (strcmp (doc->dbus_name, sender) != 0) {
306
 
                g_warning ("Failed to unregister document %s: invalid owner %s, expected %s\n",
307
 
                           uri, sender, doc->dbus_name);
308
 
                g_free (sender);
309
 
                dbus_g_method_return (method);
310
 
 
311
 
                return TRUE;
312
 
        }
313
 
        g_free (sender);
314
 
 
315
 
        ev_daemon->docs = g_list_remove (ev_daemon->docs, doc);
316
 
        ev_doc_free (doc);
317
 
        if (--ev_daemon->n_docs == 0)
318
 
                ev_daemon_start_killtimer (ev_daemon);
319
 
 
320
 
        dbus_g_method_return (method);
321
 
 
322
 
        return TRUE;
323
 
}
324
 
 
325
 
static void
326
 
do_exit (GMainLoop *loop,
327
 
         GObject   *object)
328
 
{
329
 
        if (g_main_loop_is_running (loop))
330
 
                g_main_loop_quit (loop);
331
 
}
332
 
 
333
 
static gboolean
334
 
convert_metadata (const gchar *metadata)
335
 
{
336
 
        GFile   *file;
337
 
        char    *argv[3];
338
 
        gint     exit_status;
339
 
        GFileAttributeInfoList *namespaces;
340
 
        gboolean supported = FALSE;
 
85
ev_daemon_stop_killtimer (void)
 
86
{
 
87
        if (kill_timer_id != 0)
 
88
                g_source_remove (kill_timer_id);
 
89
        kill_timer_id = 0;
 
90
}
 
91
 
 
92
static gboolean
 
93
ev_daemon_shutdown (gpointer user_data)
 
94
{
 
95
        GMainLoop *loop = (GMainLoop *) user_data;
 
96
 
 
97
        LOG ("Timeout; exiting daemon.\n");
 
98
 
 
99
        if (g_main_loop_is_running (loop))
 
100
                g_main_loop_quit (loop);
 
101
 
 
102
        return FALSE;
 
103
}
 
104
 
 
105
static void
 
106
ev_daemon_maybe_start_killtimer (gpointer data)
 
107
{
 
108
        ev_daemon_stop_killtimer ();
 
109
        if (ev_daemon_docs != NULL)
 
110
                return;
 
111
 
 
112
        kill_timer_id = g_timeout_add_seconds (DAEMON_TIMEOUT,
 
113
                                               (GSourceFunc) ev_daemon_shutdown,
 
114
                                               data);
 
115
}
 
116
 
 
117
static gboolean
 
118
spawn_evince (const gchar *uri)
 
119
{
 
120
        gchar   *argv[3];
 
121
        gboolean retval;
341
122
        GError  *error = NULL;
342
 
        gboolean retval;
343
 
 
344
 
        /* If metadata is not supported for a local file
345
 
         * is likely because and old gvfs version is running.
346
 
         */
347
 
        file = g_file_new_for_path (metadata);
348
 
        namespaces = g_file_query_writable_namespaces (file, NULL, NULL);
349
 
        if (namespaces) {
350
 
                gint i;
351
 
 
352
 
                for (i = 0; i < namespaces->n_infos; i++) {
353
 
                        if (strcmp (namespaces->infos[i].name, "metadata") == 0) {
354
 
                                supported = TRUE;
355
 
                                break;
356
 
                        }
357
 
                }
358
 
                g_file_attribute_info_list_unref (namespaces);
359
 
        }
360
 
        if (!supported) {
361
 
                g_warning ("GVFS metadata not supported. "
362
 
                           "Evince will run without metadata support.\n");
363
 
                g_object_unref (file);
364
 
                return FALSE;
365
 
        }
366
 
        g_object_unref (file);
367
 
 
368
 
        argv[0] = g_build_filename (LIBEXECDIR, "evince-convert-metadata", NULL);
369
 
        argv[1] = (char *) metadata;
 
123
 
 
124
        /* TODO Check that the uri exists */
 
125
        argv[0] = g_build_filename (BINDIR, "evince", NULL);
 
126
        argv[1] = (gchar *) uri;
370
127
        argv[2] = NULL;
371
128
 
372
 
        retval = g_spawn_sync (NULL /* wd */, argv, NULL /* env */,
373
 
                               0, NULL, NULL, NULL, NULL,
374
 
                               &exit_status, &error);
 
129
        retval = g_spawn_async (NULL /* wd */, argv, NULL /* env */,
 
130
                                0, NULL, NULL, NULL, &error);
 
131
        if (!retval) {
 
132
                g_printerr ("Error spawning evince for uri %s: %s\n", uri, error->message);
 
133
                g_error_free (error);
 
134
        }
375
135
        g_free (argv[0]);
376
136
 
377
 
        if (!retval) {
378
 
                g_printerr ("Error migrating metadata: %s\n", error->message);
 
137
        return retval;
 
138
}
 
139
 
 
140
static void
 
141
name_appeared_cb (GDBusConnection *connection,
 
142
                  const gchar     *name,
 
143
                  const gchar     *name_owner,
 
144
                  gpointer         user_data)
 
145
{
 
146
        LOG ("Watch name'%s' appeared with owner '%s'\n", name, name_owner);
 
147
}
 
148
 
 
149
static void
 
150
name_vanished_cb (GDBusConnection *connection,
 
151
                  const gchar     *name,
 
152
                  gpointer         user_data)
 
153
{
 
154
        GList *l;
 
155
 
 
156
        LOG ("Watch name'%s' disappeared\n", name);
 
157
 
 
158
        for (l = ev_daemon_docs; l != NULL; l = l->next) {
 
159
                EvDoc *doc = (EvDoc *) l->data;
 
160
 
 
161
                if (strcmp (doc->dbus_name, name) != 0)
 
162
                        continue;
 
163
 
 
164
                LOG ("Watch found URI '%s' for name; removing\n", doc->uri);
 
165
 
 
166
                ev_daemon_docs = g_list_delete_link (ev_daemon_docs, l);
 
167
                ev_doc_free (doc);
 
168
                
 
169
                ev_daemon_maybe_start_killtimer (user_data);
 
170
                return;
 
171
        }
 
172
}
 
173
 
 
174
static void
 
175
process_pending_invocations (const gchar *uri,
 
176
                             const gchar *dbus_name)
 
177
{
 
178
        GList *l;
 
179
        GList *uri_invocations;
 
180
 
 
181
        LOG ("RegisterDocument process pending invocations for URI %s\n", uri);
 
182
        uri_invocations = g_hash_table_lookup (pending_invocations, uri);
 
183
 
 
184
        for (l = uri_invocations; l != NULL; l = l->next) {
 
185
                GDBusMethodInvocation *invocation;
 
186
 
 
187
                invocation = (GDBusMethodInvocation *)l->data;
 
188
                g_dbus_method_invocation_return_value (invocation,
 
189
                                                       g_variant_new ("(s)", dbus_name));
 
190
        }
 
191
 
 
192
        g_list_free (uri_invocations);
 
193
        g_hash_table_remove (pending_invocations, uri);
 
194
}
 
195
 
 
196
static void
 
197
document_loaded_cb (GDBusConnection *connection,
 
198
                    const gchar     *sender_name,
 
199
                    const gchar     *object_path,
 
200
                    const gchar     *interface_name,
 
201
                    const gchar     *signal_name,
 
202
                    GVariant        *parameters,
 
203
                    EvDoc           *doc)
 
204
{
 
205
        const gchar *uri;
 
206
 
 
207
        g_variant_get (parameters, "(&s)", &uri);
 
208
        if (strcmp (uri, doc->uri) == 0)
 
209
                process_pending_invocations (uri, sender_name);
 
210
        g_dbus_connection_signal_unsubscribe (connection, doc->loaded_id);
 
211
}
 
212
 
 
213
static void
 
214
method_call_cb (GDBusConnection       *connection,
 
215
                const gchar           *sender,
 
216
                const gchar           *object_path,
 
217
                const gchar           *interface_name,
 
218
                const gchar           *method_name,
 
219
                GVariant              *parameters,
 
220
                GDBusMethodInvocation *invocation,
 
221
                gpointer               user_data)
 
222
{
 
223
        if (g_strcmp0 (interface_name, EV_DBUS_DAEMON_INTERFACE_NAME) != 0)
 
224
                return;
 
225
 
 
226
        if (g_strcmp0 (method_name, "RegisterDocument") == 0) {
 
227
                EvDoc       *doc;
 
228
                const gchar *uri;
 
229
 
 
230
                g_variant_get (parameters, "(&s)", &uri);
 
231
 
 
232
                doc = ev_daemon_find_doc (uri);
 
233
                if (doc != NULL) {
 
234
                        LOG ("RegisterDocument found owner '%s' for URI '%s'\n", doc->dbus_name, uri);
 
235
                        g_dbus_method_invocation_return_value (invocation,
 
236
                                                               g_variant_new ("(s)", doc->dbus_name));
 
237
                        return;
 
238
                }
 
239
 
 
240
                ev_daemon_stop_killtimer ();
 
241
 
 
242
                doc = g_new (EvDoc, 1);
 
243
                doc->dbus_name = g_strdup (sender);
 
244
                doc->uri = g_strdup (uri);
 
245
 
 
246
                doc->loaded_id = g_dbus_connection_signal_subscribe (connection,
 
247
                                                                     doc->dbus_name,
 
248
                                                                     EV_DBUS_WINDOW_INTERFACE_NAME,
 
249
                                                                     "DocumentLoaded",
 
250
                                                                     NULL,
 
251
                                                                     NULL,
 
252
                                                                     0,
 
253
                                                                     (GDBusSignalCallback) document_loaded_cb,
 
254
                                                                     doc,
 
255
                                                                     NULL);
 
256
                doc->watch_id = g_bus_watch_name_on_connection (connection,
 
257
                                                                sender,
 
258
                                                                G_BUS_NAME_WATCHER_FLAGS_NONE,
 
259
                                                                name_appeared_cb,
 
260
                                                                name_vanished_cb,
 
261
                                                                user_data, NULL);
 
262
 
 
263
                LOG ("RegisterDocument registered owner '%s' for URI '%s'\n", doc->dbus_name, uri);
 
264
                ev_daemon_docs = g_list_prepend (ev_daemon_docs, doc);
 
265
 
 
266
                g_dbus_method_invocation_return_value (invocation, g_variant_new ("(s)", ""));
 
267
        } else if (g_strcmp0 (method_name, "UnregisterDocument") == 0) {
 
268
                EvDoc *doc;
 
269
                const gchar *uri;
 
270
 
 
271
                g_variant_get (parameters, "(&s)", &uri);
 
272
 
 
273
                LOG ("UnregisterDocument URI '%s'\n", uri);
 
274
 
 
275
                doc = ev_daemon_find_doc (uri);
 
276
                if (doc == NULL) {
 
277
                        LOG ("UnregisterDocument URI was not registered!\n");
 
278
                        g_dbus_method_invocation_return_error_literal (invocation,
 
279
                                                                       G_DBUS_ERROR,
 
280
                                                                       G_DBUS_ERROR_INVALID_ARGS,
 
281
                                                                       "URI not registered");
 
282
                        return;
 
283
                }
 
284
 
 
285
                if (strcmp (doc->dbus_name, sender) != 0) {
 
286
                        LOG ("UnregisterDocument called by non-owner (owner '%s' sender '%s')\n",
 
287
                             doc->dbus_name, sender);
 
288
 
 
289
                        g_dbus_method_invocation_return_error_literal (invocation,
 
290
                                                                       G_DBUS_ERROR,
 
291
                                                                       G_DBUS_ERROR_BAD_ADDRESS,
 
292
                                                                       "Only owner can call this method");
 
293
                        return;
 
294
                }
 
295
 
 
296
                ev_daemon_docs = g_list_remove (ev_daemon_docs, doc);
 
297
                ev_doc_free (doc);
 
298
                ev_daemon_maybe_start_killtimer (user_data);
 
299
 
 
300
                g_dbus_method_invocation_return_value (invocation, g_variant_new ("()"));
 
301
        } else if (g_strcmp0 (method_name, "FindDocument") == 0) {
 
302
                EvDoc *doc;
 
303
                const gchar *uri;
 
304
                gboolean spawn;
 
305
 
 
306
                g_variant_get (parameters, "(&sb)",  &uri, &spawn);
 
307
 
 
308
                LOG ("FindDocument URI '%s' \n", uri);
 
309
 
 
310
                doc = ev_daemon_find_doc (uri);
 
311
                if (doc != NULL) {
 
312
                        g_dbus_method_invocation_return_value (invocation,
 
313
                                                               g_variant_new ("(s)", doc->dbus_name));
 
314
                        return;
 
315
                }
 
316
 
 
317
                if (spawn) {
 
318
                        GList *uri_invocations;
 
319
                        gboolean ret_val = TRUE;
 
320
 
 
321
                        uri_invocations = g_hash_table_lookup (pending_invocations, uri);
 
322
 
 
323
                        if (uri_invocations == NULL) {
 
324
                                /* Only spawn once. */
 
325
                                ret_val = spawn_evince (uri);
 
326
                        }
 
327
 
 
328
                        if (ret_val) {
 
329
                                /* Only defer DBUS answer if evince was succesfully spawned */
 
330
                                uri_invocations = g_list_prepend (uri_invocations, invocation);
 
331
                                g_hash_table_insert (pending_invocations,
 
332
                                                     g_strdup (uri),
 
333
                                                     uri_invocations);
 
334
                                return;
 
335
                        }
 
336
                }
 
337
 
 
338
                LOG ("FindDocument URI '%s' was not registered!\n", uri);
 
339
                g_dbus_method_invocation_return_value (invocation,
 
340
                                                       g_variant_new ("(s)",""));
 
341
        }
 
342
}
 
343
 
 
344
static const char introspection_xml[] =
 
345
  "<node>"
 
346
    "<interface name='org.gnome.evince.Daemon'>"
 
347
      "<method name='RegisterDocument'>"
 
348
        "<arg type='s' name='uri' direction='in'/>"
 
349
        "<arg type='s' name='owner' direction='out'/>"
 
350
      "</method>"
 
351
      "<method name='UnregisterDocument'>"
 
352
        "<arg type='s' name='uri' direction='in'/>"
 
353
      "</method>"
 
354
      "<method name='FindDocument'>"
 
355
        "<arg type='s' name='uri' direction='in'/>"
 
356
        "<arg type='b' name='spawn' direction='in'/>"
 
357
        "<arg type='s' name='owner' direction='out'/>"
 
358
      "</method>"
 
359
    "</interface>"
 
360
  "</node>";
 
361
 
 
362
static const GDBusInterfaceVTable interface_vtable = {
 
363
  method_call_cb,
 
364
  NULL,
 
365
  NULL
 
366
};
 
367
 
 
368
static GDBusNodeInfo *introspection_data;
 
369
 
 
370
static void
 
371
bus_acquired_cb (GDBusConnection *connection,
 
372
                 const gchar     *name,
 
373
                 gpointer         user_data)
 
374
{
 
375
        GMainLoop *loop = (GMainLoop *) user_data;
 
376
        guint      registration_id;
 
377
        GError    *error = NULL;
 
378
 
 
379
        if (!introspection_data)
 
380
                introspection_data = g_dbus_node_info_new_for_xml (introspection_xml, NULL);
 
381
 
 
382
        registration_id = g_dbus_connection_register_object (connection,
 
383
                                                             EV_DBUS_DAEMON_OBJECT_PATH,
 
384
                                                             introspection_data->interfaces[0],
 
385
                                                             &interface_vtable,
 
386
                                                             g_main_loop_ref (loop),
 
387
                                                             (GDestroyNotify) g_main_loop_unref,
 
388
                                                             &error);
 
389
        if (registration_id == 0) {
 
390
                g_printerr ("Failed to register object: %s\n", error->message);
379
391
                g_error_free (error);
380
 
        }
381
 
 
382
 
        return retval && WIFEXITED (exit_status) && WEXITSTATUS (exit_status) == 0;
383
 
}
384
 
 
385
 
static void
386
 
ev_migrate_metadata (void)
387
 
{
388
 
        gchar *updated;
389
 
        gchar *metadata;
390
 
        gchar *dot_dir;
391
 
 
392
 
        dot_dir = g_build_filename (g_get_home_dir (),
393
 
                                    ".gnome2",
394
 
                                    "evince",
395
 
                                    NULL);
396
 
 
397
 
        updated = g_build_filename (dot_dir, "migrated-to-gvfs", NULL);
398
 
        if (g_file_test (updated, G_FILE_TEST_EXISTS)) {
399
 
                /* Already migrated */
400
 
                g_free (updated);
401
 
                g_free (dot_dir);
402
 
                return;
403
 
        }
404
 
 
405
 
        metadata = g_build_filename (dot_dir, "ev-metadata.xml", NULL);
406
 
        if (g_file_test (metadata, G_FILE_TEST_EXISTS)) {
407
 
                if (convert_metadata (metadata)) {
408
 
                        gint fd;
409
 
 
410
 
                        fd = g_creat (updated, 0600);
411
 
                        if (fd != -1) {
412
 
                                close (fd);
413
 
                        }
414
 
                }
415
 
        }
416
 
 
417
 
        g_free (dot_dir);
418
 
        g_free (updated);
419
 
        g_free (metadata);
 
392
 
 
393
                if (g_main_loop_is_running (loop))
 
394
                        g_main_loop_quit (loop);
 
395
        }
 
396
}
 
397
 
 
398
static void
 
399
name_acquired_cb (GDBusConnection *connection,
 
400
                  const gchar     *name,
 
401
                  gpointer         user_data)
 
402
{
 
403
        ev_daemon_maybe_start_killtimer (user_data);
 
404
}
 
405
 
 
406
static void
 
407
name_lost_cb (GDBusConnection *connection,
 
408
              const gchar     *name,
 
409
              gpointer         user_data)
 
410
{
 
411
          GMainLoop *loop = (GMainLoop *) user_data;
 
412
 
 
413
          /* Failed to acquire the name; exit daemon */
 
414
          if (g_main_loop_is_running (loop))
 
415
                  g_main_loop_quit (loop);
420
416
}
421
417
 
422
418
gint
423
419
main (gint argc, gchar **argv)
424
420
{
425
421
        GMainLoop *loop;
 
422
        guint owner_id;
426
423
 
427
 
        /* Init glib threads asap */
428
 
        if (!g_thread_supported ())
429
 
                g_thread_init (NULL);
 
424
        g_set_prgname ("evince-daemon");
430
425
 
431
426
        g_type_init ();
432
427
 
433
 
        if (!ev_daemon_get ())
434
 
                return 1;
435
 
 
436
 
        ev_migrate_metadata ();
437
 
 
438
428
        loop = g_main_loop_new (NULL, FALSE);
439
 
        g_object_weak_ref (G_OBJECT (ev_daemon),
440
 
                           (GWeakNotify) do_exit,
441
 
                           loop);
442
 
        g_main_loop_run (loop);
443
 
        g_main_loop_unref (loop);
 
429
 
 
430
        pending_invocations = g_hash_table_new_full (g_str_hash,
 
431
                                                     g_str_equal,
 
432
                                                     (GDestroyNotify)g_free,
 
433
                                                     NULL);
 
434
 
 
435
        owner_id = g_bus_own_name (G_BUS_TYPE_SESSION,
 
436
                                   EV_DBUS_DAEMON_NAME,
 
437
                                   G_BUS_NAME_OWNER_FLAGS_NONE,
 
438
                                   bus_acquired_cb,
 
439
                                   name_acquired_cb,
 
440
                                   name_lost_cb,
 
441
                                   g_main_loop_ref (loop),
 
442
                                   (GDestroyNotify) g_main_loop_unref);
 
443
 
 
444
        g_main_loop_run (loop);
 
445
 
 
446
        g_bus_unown_name (owner_id);
 
447
 
 
448
        g_main_loop_unref (loop);
 
449
        if (introspection_data)
 
450
                g_dbus_node_info_unref (introspection_data);
 
451
        g_list_foreach (ev_daemon_docs, (GFunc)ev_doc_free, NULL);
 
452
        g_list_free (ev_daemon_docs);
 
453
        g_hash_table_destroy (pending_invocations);
444
454
 
445
455
        return 0;
446
456
}