Fix that bt-serivce can't find DBUS_SESSION_BUS_ADDRESS
[platform/core/connectivity/bluetooth-frwk.git] / bt-service / bt-popup.c
1 /*
2  * bluetooth-frwk
3  *
4  * Copyright (c) 2013 Intel Corporation.
5  *
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  *              http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  *
18  */
19
20 #include "bt-popup.h"
21
22 static void
23 __free_user_data(struct bt_popup_appdata *ad)
24 {
25         if (ad->agent_proxy) {
26                 g_object_unref(ad->agent_proxy);
27                 ad->agent_proxy = NULL;
28         }
29         if (ad->obex_proxy) {
30                 g_object_unref(ad->obex_proxy);
31                 ad->obex_proxy = NULL;
32         }
33         g_free(ad);
34 }
35
36 static DBusGProxy*
37 __bluetooth_create_agent_proxy(DBusGConnection *sys_conn, const char *path)
38 {
39         return dbus_g_proxy_new_for_name (      sys_conn,
40                                                 "org.projectx.bt",
41                                                 path,
42                                                 "org.bluez.Agent1");
43 }
44
45 static DBusGProxy*
46 __bluetooth_create_obex_proxy(DBusGConnection *sys_conn)
47 {
48         return dbus_g_proxy_new_for_name(       sys_conn,
49                                                 "org.bluez.frwk_agent",
50                                                 "/org/obex/ops_agent",
51                                                 "org.openobex.Agent");
52 }
53
54 static void
55 __gtk_pin_ok_cb(GtkWidget *widget, struct bt_popup_appdata *ad)
56 {
57         g_assert(ad != NULL);
58
59         dbus_g_proxy_call_no_reply(ad->agent_proxy,
60                                    "ReplyPinCode",
61                                    G_TYPE_UINT, BT_AGENT_ACCEPT,
62                                    G_TYPE_STRING, gtk_entry_get_text(GTK_ENTRY(ad->entry)),
63                                    G_TYPE_INVALID, G_TYPE_INVALID);
64
65         gtk_widget_destroy(GTK_WIDGET(ad->window));
66         __free_user_data(ad);
67 }
68
69 static void
70 __gtk_pin_cancel_cb(GtkWidget *widget, struct bt_popup_appdata *ad)
71 {
72         g_assert(ad != NULL);
73
74         dbus_g_proxy_call_no_reply(ad->agent_proxy,
75                                    "ReplyPinCode",
76                                    G_TYPE_UINT, BT_AGENT_CANCEL,
77                                    G_TYPE_STRING, "",
78                                    G_TYPE_INVALID, G_TYPE_INVALID);
79
80         gtk_widget_destroy(GTK_WIDGET(ad->window));
81         __free_user_data(ad);
82 }
83
84 static void
85 __gtk_passkey_ok_cb(GtkWidget *widget, struct bt_popup_appdata *ad)
86 {
87         g_assert(ad != NULL);
88
89         dbus_g_proxy_call_no_reply(ad->agent_proxy,
90                                    "ReplyPasskey",
91                                    G_TYPE_UINT, BT_AGENT_ACCEPT,
92                                    G_TYPE_STRING, gtk_entry_get_text(GTK_ENTRY(ad->entry)),
93                                    G_TYPE_INVALID, G_TYPE_INVALID);
94
95         gtk_widget_destroy(GTK_WIDGET(ad->window));
96         __free_user_data(ad);
97 }
98
99 static void
100 __gtk_passkey_cancel_cb(GtkWidget *widget, struct bt_popup_appdata *ad)
101 {
102         g_assert(ad != NULL);
103
104         dbus_g_proxy_call_no_reply(ad->agent_proxy,
105                                    "ReplyPasskey",
106                                    G_TYPE_UINT, BT_AGENT_CANCEL,
107                                    G_TYPE_STRING, "",
108                                    G_TYPE_INVALID, G_TYPE_INVALID);
109
110         gtk_widget_destroy(GTK_WIDGET(ad->window));
111         __free_user_data(ad);
112 }
113
114 static void
115 __notify_passkey_confirm_request_accept_cb(NotifyNotification *n, const char *action, struct bt_popup_appdata *ad)
116 {
117         g_assert(ad != NULL);
118
119         dbus_g_proxy_call_no_reply(     ad->agent_proxy, "ReplyConfirmation",
120                                         G_TYPE_UINT, BT_AGENT_ACCEPT,
121                                         G_TYPE_INVALID, G_TYPE_INVALID);
122
123         notify_notification_close(n, NULL);
124 }
125
126
127
128 static void
129 __notify_passkey_confirm_request_cancel_cb(NotifyNotification *n, const char *action, struct bt_popup_appdata *ad)
130 {
131         g_assert(ad != NULL);
132
133         dbus_g_proxy_call_no_reply(     ad->agent_proxy, "ReplyConfirmation",
134                                         G_TYPE_UINT, BT_AGENT_CANCEL,
135                                         G_TYPE_INVALID, G_TYPE_INVALID);
136
137         notify_notification_close(n, NULL);
138 }
139
140 static void
141 __notify_passkey_display_request_ok_cb(NotifyNotification *n, const char *action, struct bt_popup_appdata *ad)
142 {
143         g_assert(ad != NULL);
144
145         /* Close the popup */
146         notify_notification_close(n, NULL);
147 }
148
149 static void
150 __notify_passkey_display_request_cancel_cb(NotifyNotification *n, const char *action, struct bt_popup_appdata *ad)
151 {
152         g_assert(ad != NULL);
153
154         bluetooth_cancel_bonding();
155
156         notify_notification_close(n, NULL);
157 }
158
159 static void
160 __notify_push_authorize_request_accept_cb(NotifyNotification *n, const char *action, struct bt_popup_appdata *ad)
161 {
162         g_assert(ad != NULL);
163
164         dbus_g_proxy_call_no_reply(     ad->obex_proxy, "ReplyAuthorize",
165                                         G_TYPE_UINT, BT_AGENT_ACCEPT,
166                                         G_TYPE_INVALID, G_TYPE_INVALID);
167
168         notify_notification_close(n, NULL);
169 }
170
171 static void
172 __notify_push_authorize_request_cancel_cb(NotifyNotification *n, const char *action, struct bt_popup_appdata *ad)
173 {
174         g_assert(ad != NULL);
175
176         dbus_g_proxy_call_no_reply(     ad->obex_proxy, "ReplyAuthorize",
177                                         G_TYPE_UINT, BT_AGENT_CANCEL,
178                                         G_TYPE_INVALID, G_TYPE_INVALID);
179
180         notify_notification_close(n, NULL);
181 }
182
183 static void
184 __notify_authorize_request_accept_cb(NotifyNotification *n, const char *action, struct bt_popup_appdata *ad)
185 {
186         g_assert(ad != NULL);
187
188         dbus_g_proxy_call_no_reply(     ad->agent_proxy, "ReplyAuthorize",
189                                         G_TYPE_UINT, BT_AGENT_ACCEPT,
190                                         G_TYPE_INVALID, G_TYPE_INVALID);
191
192         notify_notification_close(n, NULL);
193 }
194
195 static void
196 __notify_authorize_request_cancel_cb(NotifyNotification *n, const char *action, struct bt_popup_appdata *ad)
197 {
198         g_assert(ad != NULL);
199
200         dbus_g_proxy_call_no_reply(     ad->agent_proxy, "ReplyAuthorize",
201                                         G_TYPE_UINT, BT_AGENT_CANCEL,
202                                         G_TYPE_INVALID, G_TYPE_INVALID);
203
204         notify_notification_close(n, NULL);
205 }
206
207 static GdkPixbuf*
208 __create_pixbuf(const gchar * filename)
209 {
210         GdkPixbuf *pixbuf;
211         GError *error = NULL;
212         pixbuf = gdk_pixbuf_new_from_file(filename, &error);
213         if(!pixbuf) {
214                 BT_ERR("%s\n", error->message);
215                 g_error_free(error);
216         }
217
218         return pixbuf;
219 }
220
221 static void
222 __close_window(GtkWidget *widget, struct bt_popup_appdata *ad)
223 {
224         gtk_widget_destroy(GTK_WIDGET(ad->window));
225 }
226
227 static int
228 __draw_input_view(      const char *event_type,
229                         struct bt_popup_appdata *ad,
230                         char *title,
231                         char* body,
232                         void *ok_cb,
233                         void *cancel_cb)
234 {
235
236         if ((!event_type) && strcasecmp(event_type, "pin-request") && strcasecmp(event_type, "passkey-request"))
237                 return BT_FAILED;
238         GtkWidget *layout;
239         GtkWidget *text_wdgt;
240         GtkWidget *image;
241         GtkWidget *ok_bt;
242         GtkWidget *cancel_bt;
243
244         gtk_init(NULL, NULL);
245         ad->window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
246         gtk_window_set_default_size(GTK_WINDOW(ad->window), 300, 100);
247         gtk_window_set_position(GTK_WINDOW(ad->window), GTK_WIN_POS_CENTER);
248         gtk_window_set_icon(GTK_WINDOW(ad->window), __create_pixbuf(NOTIFY_ICON));
249         gtk_window_set_title(GTK_WINDOW (ad->window), title);
250
251         layout = gtk_layout_new(NULL, NULL);
252         gtk_container_add(GTK_CONTAINER (ad->window), layout);
253         gtk_widget_show(layout);
254
255         image = gtk_image_new_from_file(NOTIFY_ICON);
256         gtk_layout_put(GTK_LAYOUT(layout), image, 0, 25);
257
258         text_wdgt = gtk_label_new(body);
259         gtk_layout_put(GTK_LAYOUT(layout), text_wdgt, 90, 0);
260
261         ad->entry = gtk_entry_new();
262
263         if(!strcasecmp(event_type, "pin-request"))
264                 gtk_entry_set_max_length(GTK_ENTRY(ad->entry), BT_PIN_MLEN);
265         else if (!strcasecmp(event_type, "passkey-request"))
266                 gtk_entry_set_max_length(GTK_ENTRY(ad->entry), BT_PK_MLEN);
267
268         gtk_layout_put(GTK_LAYOUT(layout), ad->entry, 90, 20);
269
270         ok_bt = gtk_button_new_with_label("Ok");
271         gtk_layout_put(GTK_LAYOUT(layout), ok_bt, 100, 50);
272         gtk_widget_set_size_request(ok_bt, 60, 35);
273
274         cancel_bt = gtk_button_new_with_label("Cancel");
275         gtk_layout_put(GTK_LAYOUT(layout), cancel_bt, 160, 50);
276         gtk_widget_set_size_request(cancel_bt, 60, 35);
277
278         g_signal_connect (ad->window, "destroy",  G_CALLBACK(__close_window), ad);
279         g_signal_connect(ok_bt, "clicked", G_CALLBACK(ok_cb), ad);
280         g_signal_connect(cancel_bt, "clicked", G_CALLBACK(cancel_cb), ad);
281
282         gtk_widget_show_all(ad->window);
283
284         return BT_SUCCESS;
285 }
286
287 static int
288 __notify_send_popup(    struct bt_popup_appdata *ad,
289                         char *body,
290                         char *action1_name,
291                         NotifyActionCallback action1_cb,
292                         char *action2_name,
293                         NotifyActionCallback action2_cb)
294 {
295         NotifyNotification *n = NULL;
296         GError *error = NULL;
297
298         n = notify_notification_new(    "Tizen Bluetooth",
299                                         body,
300                                         NOTIFY_ICON);
301         if (!n){
302                 __free_user_data(ad);
303                 BT_ERR("failed to create new notification\n");
304                 return BT_FAILED;
305         }
306
307         notify_notification_set_timeout(n, NOTIFY_EXPIRES_DEFAULT);
308
309         if (action1_name && action1_cb)
310                 notify_notification_add_action( n, "action1", action1_name,
311                                                 (NotifyActionCallback)action1_cb,
312                                                 ad,
313                                                 (GFreeFunc) __free_user_data);
314         if (action2_name && action2_cb)
315                 notify_notification_add_action( n, "action2", action2_name,
316                                                 (NotifyActionCallback)action2_cb,
317                                                 ad,
318                                                 (GFreeFunc) __free_user_data);
319         if (!notify_notification_show(n, &error)){
320                 __free_user_data(ad);
321                 BT_ERR("failed to send notification : %s\n", error->message);
322                 return BT_FAILED;
323         }
324         return BT_SUCCESS;
325 }
326
327 int
328 notify_launch(bundle * user_data)
329 {
330         int ret = 0;
331         struct bt_popup_appdata *ad;
332         ad = (struct bt_popup_appdata*) malloc ( sizeof(struct bt_popup_appdata));
333         memset(ad, 0x0, sizeof(struct bt_popup_appdata));
334         DBusGConnection *sys_conn;
335         const char *device_name = NULL;
336         const char *passkey = NULL;
337         const char *file = NULL;
338         const char *agent_path;
339         const char *event_type = NULL;
340         char *title = NULL;
341         char *body = NULL;
342
343         if (!notify_is_initted())
344                 if (!notify_init("Tizen Bluetooth-frwk")){
345                         BT_ERR("notification init failed\n");
346                         return BT_FAILED;
347                 }
348
349         event_type = bundle_get_val(user_data, "event-type");
350
351         if(!strcasecmp(event_type, "pin-request")) {
352                 device_name = (gchar*) bundle_get_val(user_data, "device-name");
353                 agent_path = bundle_get_val(user_data, "agent-path");
354
355                 sys_conn = _bt_get_system_gconn();
356                 if (sys_conn == NULL) {
357                         BT_ERR("ERROR: Can't get on system bus");
358                         return BT_FAILED;
359                 }
360
361                 ad->agent_proxy = __bluetooth_create_agent_proxy(sys_conn, agent_path);
362                 if (!ad->agent_proxy){
363                         BT_ERR("create new agent_proxy failed\n");
364                         return BT_FAILED;
365                 }
366
367                 title = g_strdup_printf("Bluetooth pairing request");
368                 body = g_strdup_printf("Enter PIN to pair with %s (Try 0000 or 1234)", device_name);
369
370                 ret = __draw_input_view(event_type, ad, title, body, &__gtk_pin_ok_cb, &__gtk_pin_cancel_cb);
371                 g_free(body);
372                 g_free(title);
373         } else if (!strcasecmp(event_type, "passkey-confirm-request")){
374                 device_name = (gchar*) bundle_get_val(user_data, "device-name");
375                 passkey = (gchar*) bundle_get_val(user_data, "passkey");
376                 agent_path = bundle_get_val(user_data, "agent-path");
377
378                 sys_conn = _bt_get_system_gconn();
379                 if (sys_conn == NULL) {
380                         BT_ERR("ERROR: Can't get on system bus");
381                         return BT_FAILED;
382                 }
383
384                 ad->agent_proxy = __bluetooth_create_agent_proxy(sys_conn, agent_path);
385                 if (!ad->agent_proxy){
386                         BT_ERR("create new agent_proxy failed\n");
387                         return BT_FAILED;
388                 }
389
390                 body = g_strdup_printf("Confirm passkey is %s to pair with %s", passkey, device_name);
391
392                 ret = __notify_send_popup(      ad,
393                                                 body,
394                                                 "Accept",
395                                                 (NotifyActionCallback) __notify_passkey_confirm_request_accept_cb,
396                                                 "Cancel",
397                                                 (NotifyActionCallback) __notify_passkey_confirm_request_cancel_cb);
398                 g_free(body);
399         }  else if (!strcasecmp(event_type, "passkey-request")) {
400                 device_name = (gchar*) bundle_get_val(user_data, "device-name");
401                 agent_path = bundle_get_val(user_data, "agent-path");
402
403                 sys_conn = _bt_get_system_gconn();
404                 if (sys_conn == NULL) {
405                         BT_ERR("ERROR: Can't get on system bus");
406                         return BT_FAILED;
407                 }
408
409                 ad->agent_proxy = __bluetooth_create_agent_proxy(sys_conn, agent_path);
410                 if (!ad->agent_proxy){
411                         BT_ERR("create new agent_proxy failed\n");
412                         return BT_FAILED;
413                 }
414
415                 title = g_strdup_printf("Bluetooth pairing request");
416                 body = g_strdup_printf("Enter PIN to pair with %s (Try 0000 or 1234)", device_name);
417
418                 ret = __draw_input_view(event_type, ad, title, body, &__gtk_passkey_ok_cb, &__gtk_passkey_cancel_cb);
419                 g_free(body);
420                 g_free(title);
421         } else if (!strcasecmp(event_type, "passkey-display-request")) {
422                 device_name = (gchar*) bundle_get_val(user_data, "device-name");
423                 passkey = (gchar*) bundle_get_val(user_data, "passkey");
424
425                 body = g_strdup_printf("Enter %s on %s to pair", passkey, device_name);
426
427                 ret = __notify_send_popup(      ad,
428                                                 body,
429                                                 "Ok",
430                                                 (NotifyActionCallback) __notify_passkey_display_request_ok_cb,
431                                                 "Cancel",
432                                                 (NotifyActionCallback) __notify_passkey_display_request_cancel_cb);
433                 g_free(body);
434         } else if (!strcasecmp(event_type, "authorize-request")) {
435                 device_name = (gchar*) bundle_get_val(user_data, "device-name");
436                 agent_path = bundle_get_val(user_data, "agent-path");
437
438                 sys_conn = _bt_get_system_gconn();
439                 if (sys_conn == NULL) {
440                         BT_ERR("ERROR: Can't get on system bus");
441                         return BT_FAILED;
442                 }
443
444                 ad->agent_proxy = __bluetooth_create_agent_proxy(sys_conn, agent_path);
445                 if (!ad->agent_proxy){
446                         BT_ERR("create new agent_proxy failed\n");
447                         return BT_FAILED;
448                 }
449
450                 body = g_strdup_printf("Allow %s to connect?", device_name);
451
452                 ret = __notify_send_popup(      ad,
453                                                 body,
454                                                 "Accept",
455                                                 (NotifyActionCallback) __notify_authorize_request_accept_cb,
456                                                 "Cancel",
457                                                 (NotifyActionCallback) __notify_authorize_request_cancel_cb);
458                 g_free(body);
459         } else if (!strcasecmp(event_type, "app-confirm-request")) {
460                 /* FIXME Seems to be an osp mechanism so not implemented to be confirmed */
461                 BT_DBG("app-confirm-request even_type seems to be an osp mechanism so not implemented in gnome environment; to be confirmed\n");
462                 ret = BT_FAILED;
463         } else if (!strcasecmp(event_type, "push-authorize-request")) {
464                 file = (gchar*) bundle_get_val(user_data, "file");
465                 device_name = (gchar*) bundle_get_val(user_data, "device-name");
466
467                 sys_conn = _bt_get_system_gconn();
468                 if (sys_conn == NULL) {
469                         BT_ERR("ERROR: Can't get on system bus");
470                         return BT_FAILED;
471                 }
472
473                 ad->obex_proxy = __bluetooth_create_obex_proxy(sys_conn);
474                 if (!ad->obex_proxy){
475                         BT_ERR("create new obex_proxy failed\n");
476                         return BT_FAILED;
477                 }
478
479                 body = g_strdup_printf("Receive %s from %s?", file, device_name);
480
481                 ret = __notify_send_popup(      ad,
482                                                 body,
483                                                 "Accept",
484                                                 (NotifyActionCallback) __notify_push_authorize_request_accept_cb,
485                                                 "Cancel",
486                                                 (NotifyActionCallback) __notify_push_authorize_request_cancel_cb);
487                 g_free(body);
488         } else if (!strcasecmp(event_type, "confirm-overwrite-request")) {
489                 /* FIXME Seems to be an osp mechanism so not implemented to be confirmed*/
490                 BT_DBG("confirm-overwrite-request even_type seems to be an osp mechanism so not implemented in gnome environment; to be confirmed\n");
491                 ret = BT_FAILED;
492         } else if (!strcasecmp(event_type, "keyboard-passkey-request")) {
493                 device_name = (gchar*) bundle_get_val(user_data, "device-name");
494                 passkey = (gchar*) bundle_get_val(user_data, "passkey");
495
496                 body = g_strdup_printf("Enter %s on %s to pair", passkey, device_name);
497
498                 ret = __notify_send_popup(      ad,
499                                                 body,
500                                                 "Ok",
501                                                 (NotifyActionCallback) __notify_passkey_display_request_ok_cb,
502                                                 "Cancel",
503                                                 (NotifyActionCallback) __notify_passkey_display_request_cancel_cb);
504                 g_free(body);
505         } else if (!strcasecmp(event_type, "bt-information")) {
506                 /* FIXME Seems to be an osp mechanism so not implemented to be confirmed */
507                 BT_DBG("bt-information even_type seems to be an osp mechanism so not implemented in gnome environment; to be confirmed\n");
508                 ret = BT_FAILED;
509         } else if (!strcasecmp(event_type, "exchange-request")) {
510                 device_name = (gchar*) bundle_get_val(user_data, "device-name");
511                 agent_path = bundle_get_val(user_data, "agent-path");
512
513                 sys_conn = _bt_get_system_gconn();
514                 if (sys_conn == NULL) {
515                         BT_ERR("ERROR: Can't get on system bus");
516                         return BT_FAILED;
517                 }
518
519                 ad->agent_proxy = __bluetooth_create_agent_proxy(sys_conn, agent_path);
520                 if (!ad->agent_proxy){
521                         BT_ERR("create new agent_proxy failed\n");
522                         return BT_FAILED;
523                 }
524
525                 body = g_strdup_printf("exchange-request from %s", device_name);
526
527                 ret = __notify_send_popup(      ad,
528                                                 body,
529                                                 "Accept",
530                                                 (NotifyActionCallback) __notify_authorize_request_accept_cb,
531                                                 "Cancel",
532                                                 (NotifyActionCallback) __notify_authorize_request_cancel_cb);
533                 g_free(body);
534         } else if (!strcasecmp(event_type, "phonebook-request")) {
535                 device_name = bundle_get_val(user_data, "device-name");
536                 agent_path = bundle_get_val(user_data, "agent-path");
537
538                 sys_conn = _bt_get_system_gconn();
539                 if (sys_conn == NULL) {
540                         BT_ERR("ERROR: Can't get on system bus");
541                         return BT_FAILED;
542                 }
543
544                 ad->agent_proxy = __bluetooth_create_agent_proxy(sys_conn, agent_path);
545                 if (!ad->agent_proxy){
546                         BT_ERR("create new agent_proxy failed\n");
547                         return BT_FAILED;
548                 }
549
550                 body = g_strdup_printf("Allow %s phonebook access", device_name);
551
552                 ret = __notify_send_popup(      ad,
553                                                 body,
554                                                 "Accept",
555                                                 (NotifyActionCallback) __notify_authorize_request_accept_cb,
556                                                 "Cancel",
557                                                 (NotifyActionCallback) __notify_authorize_request_cancel_cb);
558                 g_free(body);
559         } else if (!strcasecmp(event_type, "message-request")) {
560                 device_name = bundle_get_val(user_data, "device-name");
561                 agent_path = bundle_get_val(user_data, "agent-path");
562
563                 sys_conn = _bt_get_system_gconn();
564                 if (sys_conn == NULL) {
565                         BT_ERR("ERROR: Can't get on system bus");
566                         return BT_FAILED;
567                 }
568
569                 ad->agent_proxy = __bluetooth_create_agent_proxy(sys_conn, agent_path);
570                 if (!ad->agent_proxy){
571                         BT_ERR("create new agent_proxy failed\n");
572                         return BT_FAILED;
573                 }
574
575                 body = g_strdup_printf("Allow %s to access messages?", device_name);
576
577                 ret = __notify_send_popup(      ad,
578                                                 body,
579                                                 "Accept",
580                                                 (NotifyActionCallback) __notify_authorize_request_accept_cb,
581                                                 "Cancel",
582                                                 (NotifyActionCallback) __notify_authorize_request_cancel_cb);
583                 g_free(body);
584         } else {
585                 ret = BT_FAILED;
586         }
587
588         return ret;
589 }