261023894d48f525cc6f20558d7e0cfe3c488b83
[framework/uifw/e17.git] / src / modules / fileman / e_mod_dbus.c
1 #include "e.h"
2 #include "e_mod_main.h"
3 #include "e_mod_dbus.h"
4
5 static const char E_FILEMAN_BUS_NAME[] = "org.enlightenment.FileManager";
6 static const char E_FILEMAN_INTERFACE[] = "org.enlightenment.FileManager";
7 static const char E_FILEMAN_ERROR[] = "org.enlightenment.FileManager.Error";
8 static const char E_FILEMAN_PATH[] = "/org/enlightenment/FileManager";
9
10 typedef struct _E_Fileman_DBus_Daemon E_Fileman_DBus_Daemon;
11 struct _E_Fileman_DBus_Daemon
12 {
13    E_DBus_Connection *conn;
14    E_DBus_Interface  *iface;
15    E_DBus_Object     *obj;
16
17    struct
18    {
19       DBusPendingCall *request_name;
20    } pending;
21 };
22
23 static DBusMessage *
24 _e_fileman_dbus_daemon_error(DBusMessage *message,
25                              const char  *msg)
26 {
27    return dbus_message_new_error(message, E_FILEMAN_ERROR, msg);
28 }
29
30 static void
31 _e_fileman_dbus_daemon_object_init(E_Fileman_DBus_Daemon *d)
32 {
33    if (d->obj) return;
34
35    d->obj = e_dbus_object_add(d->conn, E_FILEMAN_PATH, d);
36    if (!d->obj)
37      {
38         fprintf(stderr, "ERROR: cannot add object to %s\n", E_FILEMAN_PATH);
39         return;
40      }
41
42    e_dbus_object_interface_attach(d->obj, d->iface);
43 }
44
45 static void
46 _e_fileman_dbus_daemon_free(E_Fileman_DBus_Daemon *d)
47 {
48    if (d->pending.request_name)
49      dbus_pending_call_cancel(d->pending.request_name);
50
51    if (d->obj)
52      {
53         e_dbus_object_interface_detach(d->obj, d->iface);
54         e_dbus_object_free(d->obj);
55      }
56
57    if (d->iface)
58      e_dbus_interface_unref(d->iface);
59
60    if (d->conn)
61      e_dbus_connection_close(d->conn);
62
63    free(d);
64 }
65
66 DBusMessage *
67 _e_fileman_dbus_daemon_open_directory_cb(E_DBus_Object *obj __UNUSED__,
68                                          DBusMessage       *message)
69 {
70    DBusMessageIter itr;
71    const char *directory = NULL, *p;
72    char *dev;
73    E_Zone *zone;
74
75    dbus_message_iter_init(message, &itr);
76    dbus_message_iter_get_basic(&itr, &directory);
77
78    if ((!directory) || (directory[0] == '\0'))
79      return _e_fileman_dbus_daemon_error(message, "no directory provided.");
80
81    if (strncmp(directory, "file://", sizeof("file://") - 1) == 0)
82      directory += sizeof("file://") - 1;
83
84    zone = e_util_zone_current_get(e_manager_current_get());
85    if (!zone)
86      return _e_fileman_dbus_daemon_error(message, "could not find a zone.");
87
88    p = strchr(directory, '/');
89    if (p)
90      {
91         int len = p - directory + 1;
92
93         dev = malloc(len + 1);
94         if (!dev)
95           return _e_fileman_dbus_daemon_error
96                    (message, "could not allocate memory.");
97
98         memcpy(dev, directory, len);
99         dev[len] = '\0';
100
101         if ((dev[0] != '/') && (dev[0] != '~'))
102           dev[len - 1] = '\0';  /* remove trailing '/' */
103
104         directory += p - directory;
105      }
106    else
107      {
108         dev = strdup(directory);
109         directory = "/";
110      }
111
112    e_fwin_new(zone->container, dev, directory);
113    free(dev);
114    return dbus_message_new_method_return(message);
115 }
116
117 static void
118 _e_fileman_dbus_daemon_request_name_cb(void        *data,
119                                        DBusMessage *msg,
120                                        DBusError   *err)
121 {
122    E_Fileman_DBus_Daemon *d = data;
123    dbus_uint32_t ret;
124    DBusError new_err;
125
126    d->pending.request_name = NULL;
127
128    if (dbus_error_is_set(err))
129      {
130         fprintf(stderr, "ERROR: FILEMAN: RequestName failed: %s\n",
131                 err->message);
132         dbus_error_free(err);
133         return;
134      }
135
136    dbus_error_init(&new_err);
137    dbus_message_get_args(msg, &new_err, DBUS_TYPE_UINT32, &ret,
138                          DBUS_TYPE_INVALID);
139
140    if (dbus_error_is_set(&new_err))
141      {
142         fprintf(stderr,
143                 "ERROR: FILEMAN: could not get arguments of RequestName: %s\n",
144                 new_err.message);
145         dbus_error_free(&new_err);
146         return;
147      }
148
149    switch (ret)
150      {
151       case DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER:
152       case DBUS_REQUEST_NAME_REPLY_ALREADY_OWNER:
153         _e_fileman_dbus_daemon_object_init(d);
154         break;
155
156       case DBUS_REQUEST_NAME_REPLY_IN_QUEUE:
157         //XXX mark daemon as queued?
158         break;
159
160       case DBUS_REQUEST_NAME_REPLY_EXISTS:
161         //XXX exit?
162         break;
163      }
164 }
165
166 static E_Fileman_DBus_Daemon *
167 _e_fileman_dbus_daemon_new(void)
168 {
169    E_Fileman_DBus_Daemon *d;
170
171    d = calloc(1, sizeof(*d));
172    if (!d)
173      {
174         perror("ERROR: FILEMAN: cannot allocate fileman dbus daemon memory.");
175         return NULL;
176      }
177
178    d->conn = e_dbus_bus_get(DBUS_BUS_SESSION);
179    if (!d->conn)
180      goto error;
181
182    d->iface = e_dbus_interface_new(E_FILEMAN_INTERFACE);
183    if (!d->iface)
184      goto error;
185
186    d->pending.request_name = e_dbus_request_name
187        (d->conn, E_FILEMAN_BUS_NAME, DBUS_NAME_FLAG_REPLACE_EXISTING,
188        _e_fileman_dbus_daemon_request_name_cb, d);
189    if (!d->pending.request_name)
190      goto error;
191
192    const struct
193    {
194       const char      *method;
195       const char      *signature;
196       const char      *ret_signature;
197       E_DBus_Method_Cb func;
198    } *itr, desc[] = {
199       {"OpenDirectory", "s", "", _e_fileman_dbus_daemon_open_directory_cb},
200       {NULL}
201    };
202
203    for (itr = desc; itr->method; itr++)
204      e_dbus_interface_method_add
205        (d->iface, itr->method, itr->signature, itr->ret_signature, itr->func);
206
207    return d;
208
209 error:
210    fprintf(stderr, "ERROR: FILEMAN: failed to create daemon at %p\n", d);
211    _e_fileman_dbus_daemon_free(d);
212    return NULL;
213 }
214
215 static E_Fileman_DBus_Daemon *_daemon = NULL;
216
217 void
218 e_fileman_dbus_init(void)
219 {
220    if (_daemon)
221      return;
222
223    e_dbus_init();
224    _daemon = _e_fileman_dbus_daemon_new();
225 }
226
227 void
228 e_fileman_dbus_shutdown(void)
229 {
230    if (!_daemon)
231      return;
232
233    _e_fileman_dbus_daemon_free(_daemon);
234    _daemon = NULL;
235    e_dbus_shutdown();
236 }
237