108
ev_daemon_finalize (GObject *object)
110
EvDaemon *ev_daemon = EV_DAEMON (object);
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;
118
if (ev_daemon->bus_proxy) {
119
g_object_unref (ev_daemon->bus_proxy);
120
ev_daemon->bus_proxy = NULL;
123
G_OBJECT_CLASS (ev_daemon_parent_class)->finalize (object);
127
ev_daemon_init (EvDaemon *ev_daemon)
132
ev_daemon_class_init (EvDaemonClass *klass)
134
GObjectClass *g_object_class = G_OBJECT_CLASS (klass);
136
g_object_class->finalize = ev_daemon_finalize;
138
dbus_g_object_type_install_info (EV_TYPE_DAEMON,
139
&dbus_glib_ev_daemon_object_info);
143
ev_daemon_shutdown (EvDaemon *ev_daemon)
145
g_object_unref (ev_daemon);
151
ev_daemon_stop_killtimer (EvDaemon *ev_daemon)
153
if (ev_daemon->timer_id != 0)
154
g_source_remove (ev_daemon->timer_id);
155
ev_daemon->timer_id = 0;
159
ev_daemon_start_killtimer (EvDaemon *ev_daemon)
161
ev_daemon_stop_killtimer (ev_daemon);
162
ev_daemon->timer_id =
163
g_timeout_add_seconds (30,
164
(GSourceFunc) ev_daemon_shutdown,
169
ev_daemon_name_owner_changed (DBusGProxy *proxy,
171
const gchar *old_owner,
172
const gchar *new_owner,
175
GList *l, *next = NULL;
177
if (*name == ':' && *new_owner == '\0') {
178
for (l = ev_daemon->docs; l; l = next) {
179
EvDoc *doc = (EvDoc *)l->data;
182
if (strcmp (doc->dbus_name, name) == 0) {
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);
195
DBusGConnection *connection;
196
guint request_name_result;
197
GError *error = NULL;
202
connection = dbus_g_bus_get (DBUS_BUS_STARTER, &error);
204
g_printerr ("Failed to connect to the D-BUS daemon: %s\n", error->message);
205
g_error_free (error);
210
ev_daemon = g_object_new (EV_TYPE_DAEMON, NULL);
212
ev_daemon->bus_proxy = dbus_g_proxy_new_for_name (connection,
215
DBUS_INTERFACE_DBUS);
216
if (!org_freedesktop_DBus_request_name (ev_daemon->bus_proxy,
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);
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);
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));
239
g_printerr ("Not primary owner of the service, exiting.\n");
240
g_object_unref (ev_daemon);
246
dbus_g_proxy_add_signal (ev_daemon->bus_proxy,
252
dbus_g_proxy_connect_signal (ev_daemon->bus_proxy, "NameOwnerChanged",
253
G_CALLBACK (ev_daemon_name_owner_changed),
255
ev_daemon_start_killtimer (ev_daemon);
263
ev_daemon_register_document (EvDaemon *ev_daemon,
265
DBusGMethodInvocation *method)
268
const gchar *owner = NULL;
270
doc = ev_daemon_find_doc (ev_daemon, uri);
272
/* Already registered */
273
owner = doc->dbus_name;
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);
283
dbus_g_method_return (method, owner);
289
ev_daemon_unregister_document (EvDaemon *ev_daemon,
291
DBusGMethodInvocation *method)
296
doc = ev_daemon_find_doc (ev_daemon, uri);
298
g_warning ("Document %s is not registered\n", uri);
299
dbus_g_method_return (method);
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);
309
dbus_g_method_return (method);
315
ev_daemon->docs = g_list_remove (ev_daemon->docs, doc);
317
if (--ev_daemon->n_docs == 0)
318
ev_daemon_start_killtimer (ev_daemon);
320
dbus_g_method_return (method);
326
do_exit (GMainLoop *loop,
329
if (g_main_loop_is_running (loop))
330
g_main_loop_quit (loop);
334
convert_metadata (const gchar *metadata)
339
GFileAttributeInfoList *namespaces;
340
gboolean supported = FALSE;
85
ev_daemon_stop_killtimer (void)
87
if (kill_timer_id != 0)
88
g_source_remove (kill_timer_id);
93
ev_daemon_shutdown (gpointer user_data)
95
GMainLoop *loop = (GMainLoop *) user_data;
97
LOG ("Timeout; exiting daemon.\n");
99
if (g_main_loop_is_running (loop))
100
g_main_loop_quit (loop);
106
ev_daemon_maybe_start_killtimer (gpointer data)
108
ev_daemon_stop_killtimer ();
109
if (ev_daemon_docs != NULL)
112
kill_timer_id = g_timeout_add_seconds (DAEMON_TIMEOUT,
113
(GSourceFunc) ev_daemon_shutdown,
118
spawn_evince (const gchar *uri)
341
122
GError *error = NULL;
344
/* If metadata is not supported for a local file
345
* is likely because and old gvfs version is running.
347
file = g_file_new_for_path (metadata);
348
namespaces = g_file_query_writable_namespaces (file, NULL, NULL);
352
for (i = 0; i < namespaces->n_infos; i++) {
353
if (strcmp (namespaces->infos[i].name, "metadata") == 0) {
358
g_file_attribute_info_list_unref (namespaces);
361
g_warning ("GVFS metadata not supported. "
362
"Evince will run without metadata support.\n");
363
g_object_unref (file);
366
g_object_unref (file);
368
argv[0] = g_build_filename (LIBEXECDIR, "evince-convert-metadata", NULL);
369
argv[1] = (char *) metadata;
124
/* TODO Check that the uri exists */
125
argv[0] = g_build_filename (BINDIR, "evince", NULL);
126
argv[1] = (gchar *) uri;
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);
132
g_printerr ("Error spawning evince for uri %s: %s\n", uri, error->message);
133
g_error_free (error);
375
135
g_free (argv[0]);
378
g_printerr ("Error migrating metadata: %s\n", error->message);
141
name_appeared_cb (GDBusConnection *connection,
143
const gchar *name_owner,
146
LOG ("Watch name'%s' appeared with owner '%s'\n", name, name_owner);
150
name_vanished_cb (GDBusConnection *connection,
156
LOG ("Watch name'%s' disappeared\n", name);
158
for (l = ev_daemon_docs; l != NULL; l = l->next) {
159
EvDoc *doc = (EvDoc *) l->data;
161
if (strcmp (doc->dbus_name, name) != 0)
164
LOG ("Watch found URI '%s' for name; removing\n", doc->uri);
166
ev_daemon_docs = g_list_delete_link (ev_daemon_docs, l);
169
ev_daemon_maybe_start_killtimer (user_data);
175
process_pending_invocations (const gchar *uri,
176
const gchar *dbus_name)
179
GList *uri_invocations;
181
LOG ("RegisterDocument process pending invocations for URI %s\n", uri);
182
uri_invocations = g_hash_table_lookup (pending_invocations, uri);
184
for (l = uri_invocations; l != NULL; l = l->next) {
185
GDBusMethodInvocation *invocation;
187
invocation = (GDBusMethodInvocation *)l->data;
188
g_dbus_method_invocation_return_value (invocation,
189
g_variant_new ("(s)", dbus_name));
192
g_list_free (uri_invocations);
193
g_hash_table_remove (pending_invocations, uri);
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,
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);
214
method_call_cb (GDBusConnection *connection,
216
const gchar *object_path,
217
const gchar *interface_name,
218
const gchar *method_name,
219
GVariant *parameters,
220
GDBusMethodInvocation *invocation,
223
if (g_strcmp0 (interface_name, EV_DBUS_DAEMON_INTERFACE_NAME) != 0)
226
if (g_strcmp0 (method_name, "RegisterDocument") == 0) {
230
g_variant_get (parameters, "(&s)", &uri);
232
doc = ev_daemon_find_doc (uri);
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));
240
ev_daemon_stop_killtimer ();
242
doc = g_new (EvDoc, 1);
243
doc->dbus_name = g_strdup (sender);
244
doc->uri = g_strdup (uri);
246
doc->loaded_id = g_dbus_connection_signal_subscribe (connection,
248
EV_DBUS_WINDOW_INTERFACE_NAME,
253
(GDBusSignalCallback) document_loaded_cb,
256
doc->watch_id = g_bus_watch_name_on_connection (connection,
258
G_BUS_NAME_WATCHER_FLAGS_NONE,
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);
266
g_dbus_method_invocation_return_value (invocation, g_variant_new ("(s)", ""));
267
} else if (g_strcmp0 (method_name, "UnregisterDocument") == 0) {
271
g_variant_get (parameters, "(&s)", &uri);
273
LOG ("UnregisterDocument URI '%s'\n", uri);
275
doc = ev_daemon_find_doc (uri);
277
LOG ("UnregisterDocument URI was not registered!\n");
278
g_dbus_method_invocation_return_error_literal (invocation,
280
G_DBUS_ERROR_INVALID_ARGS,
281
"URI not registered");
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);
289
g_dbus_method_invocation_return_error_literal (invocation,
291
G_DBUS_ERROR_BAD_ADDRESS,
292
"Only owner can call this method");
296
ev_daemon_docs = g_list_remove (ev_daemon_docs, doc);
298
ev_daemon_maybe_start_killtimer (user_data);
300
g_dbus_method_invocation_return_value (invocation, g_variant_new ("()"));
301
} else if (g_strcmp0 (method_name, "FindDocument") == 0) {
306
g_variant_get (parameters, "(&sb)", &uri, &spawn);
308
LOG ("FindDocument URI '%s' \n", uri);
310
doc = ev_daemon_find_doc (uri);
312
g_dbus_method_invocation_return_value (invocation,
313
g_variant_new ("(s)", doc->dbus_name));
318
GList *uri_invocations;
319
gboolean ret_val = TRUE;
321
uri_invocations = g_hash_table_lookup (pending_invocations, uri);
323
if (uri_invocations == NULL) {
324
/* Only spawn once. */
325
ret_val = spawn_evince (uri);
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,
338
LOG ("FindDocument URI '%s' was not registered!\n", uri);
339
g_dbus_method_invocation_return_value (invocation,
340
g_variant_new ("(s)",""));
344
static const char introspection_xml[] =
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'/>"
351
"<method name='UnregisterDocument'>"
352
"<arg type='s' name='uri' direction='in'/>"
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'/>"
362
static const GDBusInterfaceVTable interface_vtable = {
368
static GDBusNodeInfo *introspection_data;
371
bus_acquired_cb (GDBusConnection *connection,
375
GMainLoop *loop = (GMainLoop *) user_data;
376
guint registration_id;
377
GError *error = NULL;
379
if (!introspection_data)
380
introspection_data = g_dbus_node_info_new_for_xml (introspection_xml, NULL);
382
registration_id = g_dbus_connection_register_object (connection,
383
EV_DBUS_DAEMON_OBJECT_PATH,
384
introspection_data->interfaces[0],
386
g_main_loop_ref (loop),
387
(GDestroyNotify) g_main_loop_unref,
389
if (registration_id == 0) {
390
g_printerr ("Failed to register object: %s\n", error->message);
379
391
g_error_free (error);
382
return retval && WIFEXITED (exit_status) && WEXITSTATUS (exit_status) == 0;
386
ev_migrate_metadata (void)
392
dot_dir = g_build_filename (g_get_home_dir (),
397
updated = g_build_filename (dot_dir, "migrated-to-gvfs", NULL);
398
if (g_file_test (updated, G_FILE_TEST_EXISTS)) {
399
/* Already migrated */
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)) {
410
fd = g_creat (updated, 0600);
393
if (g_main_loop_is_running (loop))
394
g_main_loop_quit (loop);
399
name_acquired_cb (GDBusConnection *connection,
403
ev_daemon_maybe_start_killtimer (user_data);
407
name_lost_cb (GDBusConnection *connection,
411
GMainLoop *loop = (GMainLoop *) user_data;
413
/* Failed to acquire the name; exit daemon */
414
if (g_main_loop_is_running (loop))
415
g_main_loop_quit (loop);
423
419
main (gint argc, gchar **argv)
427
/* Init glib threads asap */
428
if (!g_thread_supported ())
429
g_thread_init (NULL);
424
g_set_prgname ("evince-daemon");
433
if (!ev_daemon_get ())
436
ev_migrate_metadata ();
438
428
loop = g_main_loop_new (NULL, FALSE);
439
g_object_weak_ref (G_OBJECT (ev_daemon),
440
(GWeakNotify) do_exit,
442
g_main_loop_run (loop);
443
g_main_loop_unref (loop);
430
pending_invocations = g_hash_table_new_full (g_str_hash,
432
(GDestroyNotify)g_free,
435
owner_id = g_bus_own_name (G_BUS_TYPE_SESSION,
437
G_BUS_NAME_OWNER_FLAGS_NONE,
441
g_main_loop_ref (loop),
442
(GDestroyNotify) g_main_loop_unref);
444
g_main_loop_run (loop);
446
g_bus_unown_name (owner_id);
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);