Code Merge [Tizen3.0]: Applied tizen.org patches
[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                         free(ad);
347                         return BT_FAILED;
348                 }
349
350         event_type = bundle_get_val(user_data, "event-type");
351
352         if(!strcasecmp(event_type, "pin-request")) {
353                 device_name = (gchar*) bundle_get_val(user_data, "device-name");
354                 agent_path = bundle_get_val(user_data, "agent-path");
355
356                 sys_conn = _bt_get_system_gconn();
357                 if (sys_conn == NULL) {
358                         BT_ERR("ERROR: Can't get on system bus");
359                         return BT_FAILED;
360                 }
361
362                 ad->agent_proxy = __bluetooth_create_agent_proxy(sys_conn, agent_path);
363                 if (!ad->agent_proxy){
364                         BT_ERR("create new agent_proxy failed\n");
365                         return BT_FAILED;
366                 }
367
368                 title = g_strdup_printf("Bluetooth pairing request");
369                 body = g_strdup_printf("Enter PIN to pair with %s (Try 0000 or 1234)", device_name);
370
371                 ret = __draw_input_view(event_type, ad, title, body, &__gtk_pin_ok_cb, &__gtk_pin_cancel_cb);
372                 g_free(body);
373                 g_free(title);
374         } else if (!strcasecmp(event_type, "passkey-confirm-request")){
375                 device_name = (gchar*) bundle_get_val(user_data, "device-name");
376                 passkey = (gchar*) bundle_get_val(user_data, "passkey");
377                 agent_path = bundle_get_val(user_data, "agent-path");
378
379                 sys_conn = _bt_get_system_gconn();
380                 if (sys_conn == NULL) {
381                         BT_ERR("ERROR: Can't get on system bus");
382                         return BT_FAILED;
383                 }
384
385                 ad->agent_proxy = __bluetooth_create_agent_proxy(sys_conn, agent_path);
386                 if (!ad->agent_proxy){
387                         BT_ERR("create new agent_proxy failed\n");
388                         return BT_FAILED;
389                 }
390
391                 body = g_strdup_printf("Confirm passkey is %s to pair with %s", passkey, device_name);
392
393                 ret = __notify_send_popup(      ad,
394                                                 body,
395                                                 "Accept",
396                                                 (NotifyActionCallback) __notify_passkey_confirm_request_accept_cb,
397                                                 "Cancel",
398                                                 (NotifyActionCallback) __notify_passkey_confirm_request_cancel_cb);
399                 g_free(body);
400         }  else if (!strcasecmp(event_type, "passkey-request")) {
401                 device_name = (gchar*) bundle_get_val(user_data, "device-name");
402                 agent_path = bundle_get_val(user_data, "agent-path");
403
404                 sys_conn = _bt_get_system_gconn();
405                 if (sys_conn == NULL) {
406                         BT_ERR("ERROR: Can't get on system bus");
407                         return BT_FAILED;
408                 }
409
410                 ad->agent_proxy = __bluetooth_create_agent_proxy(sys_conn, agent_path);
411                 if (!ad->agent_proxy){
412                         BT_ERR("create new agent_proxy failed\n");
413                         return BT_FAILED;
414                 }
415
416                 title = g_strdup_printf("Bluetooth pairing request");
417                 body = g_strdup_printf("Enter PIN to pair with %s (Try 0000 or 1234)", device_name);
418
419                 ret = __draw_input_view(event_type, ad, title, body, &__gtk_passkey_ok_cb, &__gtk_passkey_cancel_cb);
420                 g_free(body);
421                 g_free(title);
422         } else if (!strcasecmp(event_type, "passkey-display-request")) {
423                 device_name = (gchar*) bundle_get_val(user_data, "device-name");
424                 passkey = (gchar*) bundle_get_val(user_data, "passkey");
425
426                 body = g_strdup_printf("Enter %s on %s to pair", passkey, device_name);
427
428                 ret = __notify_send_popup(      ad,
429                                                 body,
430                                                 "Ok",
431                                                 (NotifyActionCallback) __notify_passkey_display_request_ok_cb,
432                                                 "Cancel",
433                                                 (NotifyActionCallback) __notify_passkey_display_request_cancel_cb);
434                 g_free(body);
435         } else if (!strcasecmp(event_type, "authorize-request")) {
436                 device_name = (gchar*) bundle_get_val(user_data, "device-name");
437                 agent_path = bundle_get_val(user_data, "agent-path");
438
439                 sys_conn = _bt_get_system_gconn();
440                 if (sys_conn == NULL) {
441                         BT_ERR("ERROR: Can't get on system bus");
442                         return BT_FAILED;
443                 }
444
445                 ad->agent_proxy = __bluetooth_create_agent_proxy(sys_conn, agent_path);
446                 if (!ad->agent_proxy){
447                         BT_ERR("create new agent_proxy failed\n");
448                         return BT_FAILED;
449                 }
450
451                 body = g_strdup_printf("Allow %s to connect?", device_name);
452
453                 ret = __notify_send_popup(      ad,
454                                                 body,
455                                                 "Accept",
456                                                 (NotifyActionCallback) __notify_authorize_request_accept_cb,
457                                                 "Cancel",
458                                                 (NotifyActionCallback) __notify_authorize_request_cancel_cb);
459                 g_free(body);
460         } else if (!strcasecmp(event_type, "app-confirm-request")) {
461                 /* FIXME Seems to be an osp mechanism so not implemented to be confirmed */
462                 BT_DBG("app-confirm-request even_type seems to be an osp mechanism so not implemented in gnome environment; to be confirmed\n");
463                 ret = BT_FAILED;
464         } else if (!strcasecmp(event_type, "push-authorize-request")) {
465                 file = (gchar*) bundle_get_val(user_data, "file");
466                 device_name = (gchar*) bundle_get_val(user_data, "device-name");
467
468                 sys_conn = _bt_get_system_gconn();
469                 if (sys_conn == NULL) {
470                         BT_ERR("ERROR: Can't get on system bus");
471                         return BT_FAILED;
472                 }
473
474                 ad->obex_proxy = __bluetooth_create_obex_proxy(sys_conn);
475                 if (!ad->obex_proxy){
476                         BT_ERR("create new obex_proxy failed\n");
477                         return BT_FAILED;
478                 }
479
480                 body = g_strdup_printf("Receive %s from %s?", file, device_name);
481
482                 ret = __notify_send_popup(      ad,
483                                                 body,
484                                                 "Accept",
485                                                 (NotifyActionCallback) __notify_push_authorize_request_accept_cb,
486                                                 "Cancel",
487                                                 (NotifyActionCallback) __notify_push_authorize_request_cancel_cb);
488                 g_free(body);
489         } else if (!strcasecmp(event_type, "confirm-overwrite-request")) {
490                 /* FIXME Seems to be an osp mechanism so not implemented to be confirmed*/
491                 BT_DBG("confirm-overwrite-request even_type seems to be an osp mechanism so not implemented in gnome environment; to be confirmed\n");
492                 ret = BT_FAILED;
493         } else if (!strcasecmp(event_type, "keyboard-passkey-request")) {
494                 device_name = (gchar*) bundle_get_val(user_data, "device-name");
495                 passkey = (gchar*) bundle_get_val(user_data, "passkey");
496
497                 body = g_strdup_printf("Enter %s on %s to pair", passkey, device_name);
498
499                 ret = __notify_send_popup(      ad,
500                                                 body,
501                                                 "Ok",
502                                                 (NotifyActionCallback) __notify_passkey_display_request_ok_cb,
503                                                 "Cancel",
504                                                 (NotifyActionCallback) __notify_passkey_display_request_cancel_cb);
505                 g_free(body);
506         } else if (!strcasecmp(event_type, "bt-information")) {
507                 /* FIXME Seems to be an osp mechanism so not implemented to be confirmed */
508                 BT_DBG("bt-information even_type seems to be an osp mechanism so not implemented in gnome environment; to be confirmed\n");
509                 ret = BT_FAILED;
510         } else if (!strcasecmp(event_type, "exchange-request")) {
511                 device_name = (gchar*) bundle_get_val(user_data, "device-name");
512                 agent_path = bundle_get_val(user_data, "agent-path");
513
514                 sys_conn = _bt_get_system_gconn();
515                 if (sys_conn == NULL) {
516                         BT_ERR("ERROR: Can't get on system bus");
517                         return BT_FAILED;
518                 }
519
520                 ad->agent_proxy = __bluetooth_create_agent_proxy(sys_conn, agent_path);
521                 if (!ad->agent_proxy){
522                         BT_ERR("create new agent_proxy failed\n");
523                         return BT_FAILED;
524                 }
525
526                 body = g_strdup_printf("exchange-request from %s", device_name);
527
528                 ret = __notify_send_popup(      ad,
529                                                 body,
530                                                 "Accept",
531                                                 (NotifyActionCallback) __notify_authorize_request_accept_cb,
532                                                 "Cancel",
533                                                 (NotifyActionCallback) __notify_authorize_request_cancel_cb);
534                 g_free(body);
535         } else if (!strcasecmp(event_type, "phonebook-request")) {
536                 device_name = bundle_get_val(user_data, "device-name");
537                 agent_path = bundle_get_val(user_data, "agent-path");
538
539                 sys_conn = _bt_get_system_gconn();
540                 if (sys_conn == NULL) {
541                         BT_ERR("ERROR: Can't get on system bus");
542                         return BT_FAILED;
543                 }
544
545                 ad->agent_proxy = __bluetooth_create_agent_proxy(sys_conn, agent_path);
546                 if (!ad->agent_proxy){
547                         BT_ERR("create new agent_proxy failed\n");
548                         return BT_FAILED;
549                 }
550
551                 body = g_strdup_printf("Allow %s phonebook access", device_name);
552
553                 ret = __notify_send_popup(      ad,
554                                                 body,
555                                                 "Accept",
556                                                 (NotifyActionCallback) __notify_authorize_request_accept_cb,
557                                                 "Cancel",
558                                                 (NotifyActionCallback) __notify_authorize_request_cancel_cb);
559                 g_free(body);
560         } else if (!strcasecmp(event_type, "message-request")) {
561                 device_name = bundle_get_val(user_data, "device-name");
562                 agent_path = bundle_get_val(user_data, "agent-path");
563
564                 sys_conn = _bt_get_system_gconn();
565                 if (sys_conn == NULL) {
566                         BT_ERR("ERROR: Can't get on system bus");
567                         return BT_FAILED;
568                 }
569
570                 ad->agent_proxy = __bluetooth_create_agent_proxy(sys_conn, agent_path);
571                 if (!ad->agent_proxy){
572                         BT_ERR("create new agent_proxy failed\n");
573                         return BT_FAILED;
574                 }
575
576                 body = g_strdup_printf("Allow %s to access messages?", device_name);
577
578                 ret = __notify_send_popup(      ad,
579                                                 body,
580                                                 "Accept",
581                                                 (NotifyActionCallback) __notify_authorize_request_accept_cb,
582                                                 "Cancel",
583                                                 (NotifyActionCallback) __notify_authorize_request_cancel_cb);
584                 g_free(body);
585         } else {
586                 ret = BT_FAILED;
587         }
588
589         return ret;
590 }