30d62b95d83cd13026e8c4f3a42f19f8ce53387a
[framework/uifw/e17.git] / src / modules / connman / e_mod_main.c
1 #include "e.h"
2 #include "e_mod_main.h"
3
4 /*
5  * STATUS:
6  *
7  *    displays current status, allows connecting and
8  *    disconnecting. needs connman 0.48 or even better from git.
9  *
10  * TODO:
11  *
12  *    MUST:
13  *       1. improve gadget ui
14  *
15  *    GOOD:
16  *       1. imporve mouse over popup ui
17  *       2. nice popup using edje objects as rows, not simple lists (fancy)
18  *       3. "Controls" for detailed information, similar to Mixer app
19  *          it would contain switches to toggle offline and choose
20  *          technologies that are enabled.
21  *
22  *    IDEAS:
23  *       1. create static connections
24  *       2. handle cellular: ask APN, Username and Password, use SetupRequired
25  *       3. handle vpn, bluetooth, wimax
26  *
27  */
28
29 static E_Module *connman_mod = NULL;
30 static char tmpbuf[PATH_MAX]; /* general purpose buffer, just use immediately */
31
32 const char _e_connman_name[] = "connman";
33 const char _e_connman_Name[] = "Connection Manager";
34 int _e_connman_log_dom = -1;
35
36 static const char *e_str_idle = NULL;
37 static const char *e_str_association = NULL;
38 static const char *e_str_configuration = NULL;
39 static const char *e_str_ready = NULL;
40 static const char *e_str_login = NULL;
41 static const char *e_str_online = NULL;
42 static const char *e_str_disconnect = NULL;
43 static const char *e_str_failure = NULL;
44
45 const char *e_str_enabled = NULL;
46 const char *e_str_available = NULL;
47 const char *e_str_connected = NULL;
48 const char *e_str_offline = NULL;
49
50 static void _connman_service_ask_pass_and_connect(E_Connman_Service *service);
51 static void _connman_default_service_changed_delayed(E_Connman_Module_Context *ctxt);
52 static void _connman_gadget_update(E_Connman_Instance *inst);
53 static void _connman_tip_update(E_Connman_Instance *inst);
54
55 const char *
56 e_connman_theme_path(void)
57 {
58 #define TF "/e-module-connman.edj"
59    size_t dirlen;
60
61    dirlen = strlen(connman_mod->dir);
62    if (dirlen >= sizeof(tmpbuf) - sizeof(TF))
63      return NULL;
64
65    memcpy(tmpbuf, connman_mod->dir, dirlen);
66    memcpy(tmpbuf + dirlen, TF, sizeof(TF));
67
68    return tmpbuf;
69 #undef TF
70 }
71
72 static void
73 _connman_toggle_offline_mode_cb(void            *data,
74                                 DBusMessage *msg __UNUSED__,
75                                 DBusError       *error)
76 {
77    E_Connman_Module_Context *ctxt = data;
78
79    if ((!error) || (!dbus_error_is_set(error)))
80      {
81         ctxt->offline_mode_pending = EINA_FALSE;
82         return;
83      }
84
85    _connman_dbus_error_show(_("Cannot toggle system's offline mode."), error);
86    dbus_error_free(error);
87 }
88
89 void
90 _connman_toggle_offline_mode(E_Connman_Module_Context *ctxt)
91 {
92    Eina_Bool offline;
93
94    if ((!ctxt) || (!ctxt->has_manager))
95      {
96         _connman_operation_error_show(_("ConnMan Daemon is not running."));
97         return;
98      }
99
100    if (!e_connman_manager_offline_mode_get(&offline))
101      {
102         _connman_operation_error_show
103           (_("Query system's offline mode."));
104         return;
105      }
106
107    offline = !offline;
108    if (!e_connman_manager_offline_mode_set
109          (offline, _connman_toggle_offline_mode_cb, ctxt))
110      {
111         _connman_operation_error_show
112           (_("Cannot toggle system's offline mode."));
113         return;
114      }
115 }
116
117 static void
118 _connman_cb_toggle_offline_mode(E_Object *obj      __UNUSED__,
119                                 const char *params __UNUSED__)
120 {
121    E_Connman_Module_Context *ctxt;
122
123    if (!connman_mod)
124      return;
125
126    ctxt = connman_mod->data;
127    _connman_toggle_offline_mode(ctxt);
128 }
129
130 struct connman_passphrase_data
131 {
132    void                      (*cb)(void       *data,
133                                    const char *password,
134                                    const char *service_path);
135    void                     *data;
136    const char               *service_path;
137    char                     *passphrase;
138    E_Connman_Module_Context *ctxt;
139    E_Dialog                 *dia;
140    Evas_Object              *entry;
141    Eina_Bool                 canceled;
142    int                       cleartext;
143 };
144
145 #if 0 // NOT WORKING, e_widget_entry_password_set() changes stops editing!!!
146 static void
147 _connman_passphrase_ask_cleartext_changed(void        *data,
148                                           Evas_Object *obj,
149                                           void *event  __UNUSED__)
150 {
151    struct connman_passphrase_data *d = data;
152    e_widget_entry_password_set(d->entry, !e_widget_check_checked_get(obj));
153    e_widget_entry_readonly_set(d->entry, 0);
154    e_widget_focus_set(d->entry, 1);
155 }
156
157 #endif
158
159 static void
160 _connman_passphrase_ask_ok(void     *data,
161                            E_Dialog *dia)
162 {
163    struct connman_passphrase_data *d = data;
164    d->canceled = EINA_FALSE;
165    e_object_del(E_OBJECT(dia));
166 }
167
168 static void
169 _connman_passphrase_ask_cancel(void     *data,
170                                E_Dialog *dia)
171 {
172    struct connman_passphrase_data *d = data;
173    d->canceled = EINA_TRUE;
174    e_object_del(E_OBJECT(dia));
175 }
176
177 static void
178 _connman_passphrase_ask_del(void *data)
179 {
180    E_Dialog *dia = data;
181    struct connman_passphrase_data *d = e_object_data_get(E_OBJECT(dia));
182
183    if (d->canceled)
184      {
185         free(d->passphrase);
186         d->passphrase = NULL;
187      }
188
189    d->cb(d->data, d->passphrase, d->service_path);
190
191    eina_stringshare_del(d->service_path);
192    free(d->passphrase);
193    E_FREE(d);
194 }
195
196 static void
197 _connman_passphrase_ask_key_down(void          *data,
198                                  Evas *e        __UNUSED__,
199                                  Evas_Object *o __UNUSED__,
200                                  void          *event)
201 {
202    Evas_Event_Key_Down *ev = event;
203    struct connman_passphrase_data *d = data;
204
205    if (strcmp(ev->keyname, "Return") == 0)
206      _connman_passphrase_ask_ok(d, d->dia);
207    else if (strcmp(ev->keyname, "Escape") == 0)
208      _connman_passphrase_ask_cancel(d, d->dia);
209 }
210
211 static void
212 _connman_passphrase_ask(E_Connman_Service                       *service,
213                         void                                     (*cb)(void *data,
214                                                      const char *password,
215                                                      const char *service_path),
216                         const void                              *data)
217 {
218    struct connman_passphrase_data *d;
219    Evas_Object *list, *o;
220    Evas *evas;
221    char buf[512];
222    const char *passphrase;
223    int mw, mh;
224
225    if (!cb)
226      return;
227    if (!service)
228      {
229         cb((void *)data, NULL, NULL);
230         return;
231      }
232
233    d = E_NEW(struct connman_passphrase_data, 1);
234    if (!d)
235      {
236         cb((void *)data, NULL, NULL);
237         return;
238      }
239    d->cb = cb;
240    d->data = (void *)data;
241    d->service_path = eina_stringshare_add(service->path);
242    d->ctxt = service->ctxt;
243    d->canceled = EINA_TRUE; /* closing the dialog defaults to cancel */
244    d->dia = e_dialog_new(NULL, "E", "connman_ask_passphrase");
245
246    e_dialog_title_set(d->dia, _("ConnMan needs your passphrase"));
247    e_dialog_icon_set(d->dia, "dialog-ask", 64);
248    e_dialog_border_icon_set(d->dia, "dialog-ask");
249
250    evas = d->dia->win->evas;
251
252    list = e_widget_list_add(evas, 0, 0);
253
254    o = edje_object_add(evas);
255    e_theme_edje_object_set(o, "base/theme/dialog",
256                            "e/widgets/dialog/text");
257    snprintf(buf, sizeof(buf),
258             _("Connection Manager needs your passphrase for <br>"
259               "the service <hilight>%s</hilight>"),
260             service->name);
261    edje_object_part_text_set(o, "e.textblock.message", buf);
262    edje_object_size_min_calc(o, &mw, &mh);
263    evas_object_size_hint_min_set(o, mw, mh);
264    evas_object_resize(o, mw, mh);
265    evas_object_show(o);
266    e_widget_list_object_append(list, o, 1, 1, 0.5);
267
268    if (!e_connman_service_passphrase_get(service->element, &passphrase))
269      passphrase = NULL;
270    if (passphrase && passphrase[0])
271      d->passphrase = strdup(passphrase);
272    else
273      d->passphrase = NULL;
274
275    d->entry = o = e_widget_entry_add(evas, &d->passphrase, NULL, NULL, NULL);
276    e_widget_entry_password_set(o, 0);
277    evas_object_show(o);
278    e_widget_list_object_append(list, o, 1, 0, 0.0);
279
280 #if 0 // NOT WORKING, e_widget_entry_password_set() changes stops editing!!!
281    d->cleartext = 1;
282    o = e_widget_check_add(evas, _("Show passphrase as clear text"),
283                           &d->cleartext);
284    evas_object_smart_callback_add
285      (o, "changed", _connman_passphrase_ask_cleartext_changed, d);
286    evas_object_show(o);
287    e_widget_list_object_append(list, o, 1, 0, 0.0);
288 #endif
289
290    e_widget_size_min_get(list, &mw, &mh);
291    if (mw < 200)
292      mw = 200;
293    if (mh < 60)
294      mh = 60;
295    e_dialog_content_set(d->dia, list, mw, mh);
296
297    e_dialog_button_add
298      (d->dia, _("Ok"), NULL, _connman_passphrase_ask_ok, d);
299    e_dialog_button_add
300      (d->dia, _("Cancel"), NULL, _connman_passphrase_ask_cancel, d);
301
302    evas_object_event_callback_add
303      (d->dia->bg_object, EVAS_CALLBACK_KEY_DOWN,
304      _connman_passphrase_ask_key_down, d);
305
306    e_object_del_attach_func_set
307      (E_OBJECT(d->dia), _connman_passphrase_ask_del);
308    e_object_data_set(E_OBJECT(d->dia), d);
309
310    e_dialog_button_focus_num(d->dia, 0);
311    e_widget_focus_set(d->entry, 1);
312
313    e_win_centered_set(d->dia->win, 1);
314    e_dialog_show(d->dia);
315 }
316
317 static void
318 _connman_service_free(E_Connman_Service *service)
319 {
320    eina_stringshare_del(service->path);
321    eina_stringshare_del(service->name);
322    eina_stringshare_del(service->type);
323    eina_stringshare_del(service->mode);
324    eina_stringshare_del(service->state);
325    eina_stringshare_del(service->error);
326    eina_stringshare_del(service->security);
327    eina_stringshare_del(service->ipv4_method);
328    eina_stringshare_del(service->ipv4_address);
329    eina_stringshare_del(service->ipv4_netmask);
330
331    E_FREE(service);
332 }
333
334 static void
335 _connman_service_changed(void                    *data,
336                          const E_Connman_Element *element)
337 {
338    E_Connman_Service *service = data;
339    const char *str;
340    unsigned char u8;
341    Eina_Bool b;
342
343 #define GSTR(name_, getter)   \
344   str = NULL;                 \
345   if (!getter(element, &str)) \
346     str = NULL;               \
347   eina_stringshare_replace(&service->name_, str)
348
349    GSTR(name, e_connman_service_name_get);
350    GSTR(type, e_connman_service_type_get);
351    GSTR(mode, e_connman_service_mode_get);
352    GSTR(state, e_connman_service_state_get);
353    GSTR(error, e_connman_service_error_get);
354    GSTR(security, e_connman_service_security_get);
355    GSTR(ipv4_method, e_connman_service_ipv4_configuration_method_get);
356
357    if (service->ipv4_method && strcmp(service->ipv4_method, "dhcp") == 0)
358      {
359         GSTR(ipv4_address, e_connman_service_ipv4_address_get);
360         GSTR(ipv4_netmask, e_connman_service_ipv4_netmask_get);
361      }
362    else
363      {
364         GSTR(ipv4_address,
365              e_connman_service_ipv4_configuration_address_get);
366         GSTR(ipv4_netmask,
367              e_connman_service_ipv4_configuration_netmask_get);
368      }
369 #undef GSTR
370
371    if ((service->state != e_str_failure) && (service->error))
372      eina_stringshare_replace(&service->error, NULL);
373
374    if (!e_connman_service_strength_get(element, &u8))
375      u8 = 0;
376    service->strength = u8;
377
378 #define GBOOL(name_, getter) \
379   b = EINA_FALSE;            \
380   if (!getter(element, &b))  \
381     b = EINA_FALSE;          \
382   service->name_ = b
383
384    GBOOL(favorite, e_connman_service_favorite_get);
385    GBOOL(auto_connect, e_connman_service_auto_connect_get);
386    GBOOL(pass_required, e_connman_service_passphrase_required_get);
387 #undef GBOOL
388
389    if ((service->ctxt->default_service == service) ||
390        (!service->ctxt->default_service))
391      _connman_default_service_changed_delayed(service->ctxt);
392    else
393      DBG("Do not request for delayed changed as this is not the default.");
394 }
395
396 static void
397 _connman_service_freed(void *data)
398 {
399    E_Connman_Service *service = data;
400    E_Connman_Module_Context *ctxt = service->ctxt;
401
402    ctxt->services = eina_inlist_remove
403        (ctxt->services, EINA_INLIST_GET(service));
404
405    _connman_service_free(service);
406
407    if (ctxt->default_service == service)
408      {
409         ctxt->default_service = NULL;
410         _connman_default_service_changed_delayed(ctxt);
411      }
412 }
413
414 static E_Connman_Service *
415 _connman_service_new(E_Connman_Module_Context *ctxt,
416                      E_Connman_Element        *element)
417 {
418    E_Connman_Service *service;
419    const char *str;
420    unsigned char u8;
421    Eina_Bool b;
422
423    if (!element)
424      return NULL;
425
426    service = E_NEW(E_Connman_Service, 1);
427    if (!service)
428      return NULL;
429
430    service->ctxt = ctxt;
431    service->element = element;
432    service->path = eina_stringshare_add(element->path);
433
434 #define GSTR(name_, getter)   \
435   str = NULL;                 \
436   if (!getter(element, &str)) \
437     str = NULL;               \
438   service->name_ = eina_stringshare_add(str)
439
440    GSTR(name, e_connman_service_name_get);
441    GSTR(type, e_connman_service_type_get);
442    GSTR(mode, e_connman_service_mode_get);
443    GSTR(state, e_connman_service_state_get);
444    GSTR(error, e_connman_service_error_get);
445    GSTR(security, e_connman_service_security_get);
446    GSTR(ipv4_method, e_connman_service_ipv4_method_get);
447    GSTR(ipv4_address, e_connman_service_ipv4_address_get);
448    GSTR(ipv4_netmask, e_connman_service_ipv4_netmask_get);
449 #undef GSTR
450
451    if ((service->state != e_str_failure) && (service->error))
452      eina_stringshare_replace(&service->error, NULL);
453
454    if (!e_connman_service_strength_get(element, &u8))
455      u8 = 0;
456    service->strength = u8;
457
458 #define GBOOL(name_, getter) \
459   b = EINA_FALSE;            \
460   if (!getter(element, &b))  \
461     b = EINA_FALSE;          \
462   service->name_ = b
463
464    GBOOL(favorite, e_connman_service_favorite_get);
465    GBOOL(auto_connect, e_connman_service_auto_connect_get);
466    GBOOL(pass_required, e_connman_service_passphrase_required_get);
467 #undef GBOOL
468
469    e_connman_element_listener_add
470      (element, _connman_service_changed, service,
471      _connman_service_freed);
472
473    return service;
474 }
475
476 #define GSTR(name_, getter)   \
477   str = NULL;                 \
478   if (!getter(element, &str)) \
479     str = NULL;               \
480   eina_stringshare_replace(&t->name_, str)
481
482 static void
483 _connman_technology_free(E_Connman_Technology *t)
484 {
485    eina_stringshare_del(t->path);
486    eina_stringshare_del(t->name);
487    eina_stringshare_del(t->type);
488    eina_stringshare_del(t->state);
489
490    E_FREE(t);
491 }
492
493 static void
494 _connman_technology_changed(void                    *data,
495                             const E_Connman_Element *element)
496 {
497    E_Connman_Technology *t = data;
498    const char *str;
499
500    GSTR(name, e_connman_technology_name_get);
501    GSTR(type, e_connman_technology_type_get);
502    GSTR(state, e_connman_technology_state_get);
503 }
504
505 static void
506 _connman_technology_freed(void *data)
507 {
508    E_Connman_Technology *t = data;
509    E_Connman_Module_Context *ctxt = t->ctxt;
510
511    ctxt->technologies = eina_inlist_remove
512        (ctxt->technologies, EINA_INLIST_GET(t));
513
514    _connman_technology_free(t);
515 }
516
517 static E_Connman_Technology *
518 _connman_technology_new(E_Connman_Module_Context *ctxt,
519                         E_Connman_Element        *element)
520 {
521    E_Connman_Technology *t;
522    const char *str;
523
524    if (!element)
525      return NULL;
526
527    t = E_NEW(E_Connman_Technology, 1);
528    if (!t)
529      return NULL;
530
531    t->ctxt = ctxt;
532    t->element = element;
533    t->path = eina_stringshare_add(element->path);
534
535    GSTR(name, e_connman_technology_name_get);
536    GSTR(type, e_connman_technology_type_get);
537    GSTR(state, e_connman_technology_state_get);
538
539    e_connman_element_listener_add
540      (element, _connman_technology_changed, t,
541      _connman_technology_freed);
542
543    return t;
544 }
545
546 #undef GSTR
547
548 static void
549 _connman_service_disconnect_cb(void            *data,
550                                DBusMessage *msg __UNUSED__,
551                                DBusError       *error)
552 {
553    E_Connman_Module_Context *ctxt = data;
554
555    if (error && dbus_error_is_set(error))
556      {
557         if (strcmp(error->name,
558                    "org.moblin.connman.Error.NotConnected") != 0)
559           _connman_dbus_error_show(_("Disconnect from network service."),
560                                    error);
561         dbus_error_free(error);
562      }
563
564    _connman_default_service_changed_delayed(ctxt);
565 }
566
567 static void
568 _connman_service_disconnect(E_Connman_Service *service)
569 {
570    if (!e_connman_service_disconnect
571          (service->element, _connman_service_disconnect_cb, service->ctxt))
572      _connman_operation_error_show(_("Disconnect from network service."));
573 }
574
575 struct connman_service_connect_data
576 {
577    const char               *service_path;
578    E_Connman_Module_Context *ctxt;
579 };
580
581 static void
582 _connman_service_connect_cb(void            *data,
583                             DBusMessage *msg __UNUSED__,
584                             DBusError       *error)
585 {
586    struct connman_service_connect_data *d = data;
587
588    if (error && dbus_error_is_set(error))
589      {
590         /* TODO: cellular might ask for SetupRequired to enter APN,
591          * username and password
592          */
593           if ((strcmp(error->name,
594                       "org.moblin.connman.Error.PassphraseRequired") == 0) ||
595               (strcmp(error->name,
596                       "org.moblin.connman.Error.Failed") == 0))
597             {
598                E_Connman_Service *service;
599
600                service = _connman_ctxt_find_service_stringshare
601                    (d->ctxt, d->service_path);
602                if (!service)
603                  _connman_operation_error_show
604                    (_("Service does not exist anymore"));
605                else if (strcmp(service->type, "wifi") == 0)
606                  {
607                     _connman_service_disconnect(service);
608                     _connman_service_ask_pass_and_connect(service);
609                  }
610                else
611      /* TODO: cellular might ask for user and pass */
612                  _connman_dbus_error_show(_("Connect to network service."),
613                                           error);
614             }
615           else if (strcmp(error->name,
616                           "org.moblin.connman.Error.AlreadyConnected") != 0)
617             _connman_dbus_error_show(_("Connect to network service."), error);
618
619           dbus_error_free(error);
620      }
621
622    _connman_default_service_changed_delayed(d->ctxt);
623    eina_stringshare_del(d->service_path);
624    E_FREE(d);
625 }
626
627 static void
628 _connman_service_connect(E_Connman_Service *service)
629 {
630    struct connman_service_connect_data *d;
631
632    d = E_NEW(struct connman_service_connect_data, 1);
633    if (!d)
634      return;
635
636    d->service_path = eina_stringshare_ref(service->path);
637    d->ctxt = service->ctxt;
638
639    if (!e_connman_service_connect
640          (service->element, _connman_service_connect_cb, d))
641      {
642         eina_stringshare_del(d->service_path);
643         E_FREE(d);
644         _connman_operation_error_show(_("Connect to network service."));
645      }
646 }
647
648 struct connman_service_ask_pass_data
649 {
650    const char               *service_path;
651    E_Connman_Module_Context *ctxt;
652 };
653
654 static void
655 _connman_service_ask_pass_and_connect__set_cb(void            *data,
656                                               DBusMessage *msg __UNUSED__,
657                                               DBusError       *error)
658 {
659    struct connman_service_ask_pass_data *d = data;
660    E_Connman_Service *service;
661
662    service = _connman_ctxt_find_service_stringshare(d->ctxt, d->service_path);
663    if (!service)
664      {
665         _connman_operation_error_show(_("Service does not exist anymore"));
666         goto end;
667      }
668
669    if ((!error) || (!dbus_error_is_set(error)))
670      _connman_service_connect(service);
671
672 end:
673    if ((error) && (dbus_error_is_set(error)))
674      dbus_error_free(error);
675    eina_stringshare_del(d->service_path);
676    E_FREE(d);
677 }
678
679 static void
680 _connman_service_ask_pass_and_connect__ask_cb(void       *data,
681                                               const char *passphrase,
682                                               const char *service_path)
683 {
684    E_Connman_Module_Context *ctxt = data;
685    E_Connman_Service *service;
686    struct connman_service_ask_pass_data *d;
687
688    service = _connman_ctxt_find_service_stringshare(ctxt, service_path);
689    if (!service)
690      {
691         _connman_operation_error_show(_("Service does not exist anymore"));
692         return;
693      }
694
695    if (!passphrase)
696      {
697         _connman_service_disconnect(service);
698         return;
699      }
700
701    d = E_NEW(struct connman_service_ask_pass_data, 1);
702    if (!d)
703      return;
704    d->service_path = eina_stringshare_ref(service_path);
705    d->ctxt = ctxt;
706
707    if (!e_connman_service_passphrase_set
708          (service->element, passphrase,
709          _connman_service_ask_pass_and_connect__set_cb, d))
710      {
711         eina_stringshare_del(d->service_path);
712         E_FREE(d);
713         _connman_operation_error_show(_("Could not set service's passphrase"));
714         return;
715      }
716 }
717
718 static void
719 _connman_service_ask_pass_and_connect(E_Connman_Service *service)
720 {
721    _connman_passphrase_ask
722      (service, _connman_service_ask_pass_and_connect__ask_cb, service->ctxt);
723 }
724
725 static void
726 _connman_services_free(E_Connman_Module_Context *ctxt)
727 {
728    while (ctxt->services)
729      {
730         E_Connman_Service *service = (E_Connman_Service *)ctxt->services;
731         e_connman_element_listener_del
732           (service->element, _connman_service_changed, service);
733         /* no need for free or unlink, since listener_del() calls
734          * _connman_service_freed()
735          */
736         //ctxt->services = eina_inlist_remove(ctxt->services, ctxt->services);
737         //_connman_service_free(service);
738      }
739 }
740
741 static inline Eina_Bool
742 _connman_services_element_exists(const E_Connman_Module_Context *ctxt,
743                                  const E_Connman_Element        *element)
744 {
745    const E_Connman_Service *service;
746
747    EINA_INLIST_FOREACH(ctxt->services, service)
748      if (service->path == element->path)
749        return EINA_TRUE;
750
751    return EINA_FALSE;
752 }
753
754 static inline Eina_Bool
755 _connman_technologies_element_exists(const E_Connman_Module_Context *ctxt,
756                                      const E_Connman_Element        *element)
757 {
758    const E_Connman_Technology *t;
759
760    EINA_INLIST_FOREACH(ctxt->technologies, t)
761      {
762         if (t->path == element->path)
763           return EINA_TRUE;
764      }
765
766    return EINA_FALSE;
767 }
768
769 void
770 _connman_request_scan_cb(void *data       __UNUSED__,
771                          DBusMessage *msg __UNUSED__,
772                          DBusError       *error)
773 {
774    if (error && dbus_error_is_set(error))
775      {
776         ERR("%s method failed with message \'%s\'", error->name, error->message);
777         dbus_error_free(error);
778      }
779
780    return;
781 }
782
783 static void
784 _connman_technologies_load(E_Connman_Module_Context *ctxt)
785 {
786    unsigned int count, i;
787    E_Connman_Element **elements;
788
789    if (!e_connman_manager_technologies_get(&count, &elements))
790      return;
791
792    DBG("Technologies = %d.", count);
793    for (i = 0; i < count; i++)
794      {
795         E_Connman_Element *e = elements[i];
796         E_Connman_Technology *t;
797
798         if ((!e) || _connman_technologies_element_exists(ctxt, e))
799           continue;
800
801         t = _connman_technology_new(ctxt, e);
802         if (!t)
803           continue;
804
805         DBG("Added technology: %s.", t->name);
806         ctxt->technologies = eina_inlist_append
807             (ctxt->technologies, EINA_INLIST_GET(t));
808      }
809
810    if (!e_connman_manager_request_scan("", _connman_request_scan_cb, NULL))
811      ERR("Request scan on all technologies failed.");
812
813    free(elements);
814 }
815
816 static void
817 _connman_services_load(E_Connman_Module_Context *ctxt)
818 {
819    unsigned int i, count;
820    E_Connman_Element **elements;
821
822    if (!e_connman_manager_services_get(&count, &elements))
823      return;
824
825    for (i = 0; i < count; i++)
826      {
827         E_Connman_Element *e = elements[i];
828         E_Connman_Service *service;
829
830         if ((!e) || (_connman_services_element_exists(ctxt, e)))
831           continue;
832
833         service = _connman_service_new(ctxt, e);
834         if (!service)
835           continue;
836
837         DBG("Added service: %s\n", service->name);
838         ctxt->services = eina_inlist_append
839             (ctxt->services, EINA_INLIST_GET(service));
840      }
841
842    /* no need to remove elements, as they remove themselves */
843    free(elements);
844 }
845
846 static void
847 _connman_default_service_changed(E_Connman_Module_Context *ctxt)
848 {
849    E_Connman_Service *itr, *def = NULL;
850    E_Connman_Instance *inst;
851    const Eina_List *l;
852    const char *tech;
853
854    EINA_INLIST_FOREACH(ctxt->services, itr)
855      {
856         if ((itr->state == e_str_ready) ||
857             (itr->state == e_str_login) ||
858             (itr->state == e_str_online))
859           {
860              def = itr;
861              break;
862           }
863         else if ((itr->state == e_str_association) &&
864                  ((!def) || (def && def->state != e_str_configuration)))
865           def = itr;
866         else if (itr->state == e_str_configuration)
867           def = itr;
868      }
869
870    DBG("Default service changed to %p (%s)", def, def ? def->name : "");
871
872    if (!e_connman_manager_technology_default_get(&tech))
873      tech = NULL;
874    if (eina_stringshare_replace(&ctxt->technology, tech))
875      DBG("Manager technology is '%s'", tech);
876
877    if (!e_connman_manager_offline_mode_get(&ctxt->offline_mode))
878      ctxt->offline_mode = EINA_FALSE;
879
880    if ((e_config->mode.offline != ctxt->offline_mode) &&
881        (!ctxt->offline_mode_pending))
882      {
883         e_config->mode.offline = ctxt->offline_mode;
884         e_config_mode_changed();
885         e_config_save_queue();
886      }
887
888    ctxt->default_service = def;
889    EINA_LIST_FOREACH(ctxt->instances, l, inst)
890      _connman_gadget_update(inst);
891 }
892
893 static void
894 _connman_services_reload(E_Connman_Module_Context *ctxt)
895 {
896    _connman_services_load(ctxt);
897    _connman_default_service_changed(ctxt);
898 }
899
900 static Eina_Bool
901 _connman_default_service_changed_delayed_do(void *data)
902 {
903    E_Connman_Module_Context *ctxt = data;
904    DBG("Do delayed change.");
905
906    ctxt->poller.default_service_changed = NULL;
907    _connman_default_service_changed(ctxt);
908    return ECORE_CALLBACK_CANCEL;
909 }
910
911 static void
912 _connman_default_service_changed_delayed(E_Connman_Module_Context *ctxt)
913 {
914    if (!ctxt->has_manager)
915      return;
916    DBG("Request delayed change.");
917    if (ctxt->poller.default_service_changed)
918      ecore_poller_del(ctxt->poller.default_service_changed);
919    ctxt->poller.default_service_changed = ecore_poller_add
920        (ECORE_POLLER_CORE, 1, _connman_default_service_changed_delayed_do, ctxt);
921 }
922
923 static void _connman_popup_del(E_Connman_Instance *inst);
924
925 static Eina_Bool
926 _connman_popup_input_window_mouse_up_cb(void    *data,
927                                         int type __UNUSED__,
928                                         void    *event)
929 {
930    Ecore_Event_Mouse_Button *ev = event;
931    E_Connman_Instance *inst = data;
932
933    if (ev->window != inst->ui.input.win)
934      return ECORE_CALLBACK_PASS_ON;
935
936    _connman_popup_del(inst);
937
938    return ECORE_CALLBACK_PASS_ON;
939 }
940
941 static Eina_Bool
942 _connman_popup_input_window_key_down_cb(void    *data,
943                                         int type __UNUSED__,
944                                         void    *event)
945 {
946    Ecore_Event_Key *ev = event;
947    E_Connman_Instance *inst = data;
948    const char *keysym;
949
950    if (ev->window != inst->ui.input.win)
951      return ECORE_CALLBACK_PASS_ON;
952
953    keysym = ev->key;
954    if (strcmp(keysym, "Escape") == 0)
955      _connman_popup_del(inst);
956
957    return ECORE_CALLBACK_PASS_ON;
958 }
959
960 static void
961 _connman_popup_input_window_destroy(E_Connman_Instance *inst)
962 {
963    ecore_x_window_free(inst->ui.input.win);
964    inst->ui.input.win = 0;
965
966    ecore_event_handler_del(inst->ui.input.mouse_up);
967    inst->ui.input.mouse_up = NULL;
968
969    ecore_event_handler_del(inst->ui.input.key_down);
970    inst->ui.input.key_down = NULL;
971 }
972
973 static void
974 _connman_popup_input_window_create(E_Connman_Instance *inst)
975 {
976    Ecore_X_Window_Configure_Mask mask;
977    Ecore_X_Window w, popup_w;
978    E_Manager *man;
979
980    man = e_manager_current_get();
981
982    w = ecore_x_window_input_new(man->root, 0, 0, man->w, man->h);
983    mask = (ECORE_X_WINDOW_CONFIGURE_MASK_STACK_MODE |
984            ECORE_X_WINDOW_CONFIGURE_MASK_SIBLING);
985    popup_w = inst->popup->win->evas_win;
986    ecore_x_window_configure(w, mask, 0, 0, 0, 0, 0, popup_w,
987                             ECORE_X_WINDOW_STACK_BELOW);
988    ecore_x_window_show(w);
989
990    inst->ui.input.mouse_up =
991      ecore_event_handler_add(ECORE_EVENT_MOUSE_BUTTON_UP,
992                              _connman_popup_input_window_mouse_up_cb, inst);
993
994    inst->ui.input.key_down =
995      ecore_event_handler_add(ECORE_EVENT_KEY_DOWN,
996                              _connman_popup_input_window_key_down_cb, inst);
997
998    inst->ui.input.win = w;
999 }
1000
1001 static void
1002 _connman_popup_cb_offline_mode_changed(void        *data,
1003                                        Evas_Object *obj)
1004 {
1005    E_Connman_Instance *inst = data;
1006    E_Connman_Module_Context *ctxt = inst->ctxt;
1007    Eina_Bool offline = e_widget_check_checked_get(obj);
1008
1009    if ((!ctxt) || (!ctxt->has_manager))
1010      {
1011         _connman_operation_error_show(_("ConnMan Daemon is not running."));
1012         return;
1013      }
1014
1015    if (!e_connman_manager_offline_mode_set
1016          (offline, _connman_toggle_offline_mode_cb, ctxt))
1017      {
1018         _connman_operation_error_show
1019           (_("Cannot toggle system's offline mode."));
1020         return;
1021      }
1022    ctxt->offline_mode_pending = EINA_TRUE;
1023 }
1024
1025 static void
1026 _connman_popup_cb_controls(void       *data,
1027                            void *data2 __UNUSED__)
1028 {
1029    E_Connman_Instance *inst = data;
1030
1031    if (!inst)
1032      return;
1033    if (inst->popup)
1034      _connman_popup_del(inst);
1035    if (inst->ctxt->conf_dialog)
1036      return;
1037
1038    inst->ctxt->conf_dialog = e_connman_config_dialog_new(NULL, inst->ctxt);
1039 }
1040
1041 static void
1042 _connman_popup_service_selected(void *data)
1043 {
1044    E_Connman_Instance *inst = data;
1045    E_Connman_Module_Context *ctxt = inst->ctxt;
1046    E_Connman_Service *service;
1047
1048    if (inst->first_selection)
1049      {
1050         inst->first_selection = EINA_FALSE;
1051         return;
1052      }
1053
1054    if (!inst->service_path)
1055      return;
1056
1057    service = _connman_ctxt_find_service_stringshare(ctxt, inst->service_path);
1058    if (!service)
1059      return;
1060
1061    _connman_popup_del(inst);
1062
1063    if ((service->state != e_str_idle) &&
1064        (service->state != e_str_disconnect) &&
1065        (service->state != e_str_failure))
1066      _connman_service_disconnect(service);
1067    else if (service->pass_required)
1068      _connman_service_ask_pass_and_connect(service);
1069    else
1070      _connman_service_connect(service);
1071 }
1072
1073 Evas_Object *
1074 _connman_service_new_list_item(Evas              *evas,
1075                                E_Connman_Service *service)
1076 {
1077    Evas_Object *icon;
1078    Edje_Message_Int msg;
1079    char buf[128];
1080
1081    snprintf(buf, sizeof(buf), "e/modules/connman/icon/%s", service->type);
1082    icon = edje_object_add(evas);
1083    e_theme_edje_object_set(icon, "base/theme/modules/connman", buf);
1084
1085    snprintf(buf, sizeof(buf), "e,state,%s", service->state);
1086    edje_object_signal_emit(icon, buf, "e");
1087
1088    if (service->mode)
1089      {
1090         snprintf(buf, sizeof(buf), "e,mode,%s", service->mode);
1091         edje_object_signal_emit(icon, buf, "e");
1092      }
1093
1094    if (service->security)
1095      {
1096         snprintf(buf, sizeof(buf), "e,security,%s", service->security);
1097         edje_object_signal_emit(icon, buf, "e");
1098      }
1099
1100    if (service->favorite)
1101      edje_object_signal_emit(icon, "e,favorite,yes", "e");
1102    else
1103      edje_object_signal_emit(icon, "e,favorite,no", "e");
1104
1105    if (service->auto_connect)
1106      edje_object_signal_emit(icon, "e,auto_connect,yes", "e");
1107    else
1108      edje_object_signal_emit(icon, "e,auto_connect,no", "e");
1109
1110    if (service->pass_required)
1111      edje_object_signal_emit(icon, "e,pass_required,yes", "e");
1112    else
1113      edje_object_signal_emit(icon, "e,pass_required,no", "e");
1114
1115    msg.val = service->strength;
1116    edje_object_message_send(icon, EDJE_MESSAGE_INT, 1, &msg);
1117
1118    return icon;
1119 }
1120
1121 static void
1122 _connman_popup_update(E_Connman_Instance *inst)
1123 {
1124    Evas_Object *list = inst->ui.list;
1125    E_Connman_Service *service;
1126    const char *default_path;
1127    Evas *evas = evas_object_evas_get(list);
1128    int i, selected;
1129
1130    default_path = inst->ctxt->default_service ?
1131      inst->ctxt->default_service->path : NULL;
1132
1133    /* TODO: replace this with a scroller + list of edje
1134     * objects that are more full of features
1135     */
1136    e_widget_ilist_freeze(list);
1137    e_widget_ilist_clear(list);
1138    i = 0;
1139    selected = -1;
1140    EINA_INLIST_FOREACH(inst->ctxt->services, service)
1141      {
1142         Evas_Object *icon;
1143
1144         if (service->path == default_path)
1145           selected = i;
1146         i++;
1147
1148         icon = _connman_service_new_list_item(evas, service);
1149
1150         e_widget_ilist_append
1151           (list, icon, service->name, _connman_popup_service_selected,
1152           inst, service->path);
1153      }
1154
1155    if (selected >= 0)
1156      {
1157         inst->first_selection = EINA_TRUE;
1158         e_widget_ilist_selected_set(list, selected);
1159      }
1160    else
1161      inst->first_selection = EINA_FALSE;
1162
1163    e_widget_ilist_thaw(list);
1164    e_widget_ilist_go(list);
1165
1166    e_widget_check_checked_set(inst->ui.offline_mode, inst->ctxt->offline_mode);
1167 }
1168
1169 static void
1170 _connman_popup_del(E_Connman_Instance *inst)
1171 {
1172    eina_stringshare_replace(&inst->service_path, NULL);
1173    _connman_popup_input_window_destroy(inst);
1174    e_object_del(E_OBJECT(inst->popup));
1175    inst->popup = NULL;
1176 }
1177
1178 static void
1179 _connman_popup_new(E_Connman_Instance *inst)
1180 {
1181    E_Connman_Module_Context *ctxt = inst->ctxt;
1182    Evas *evas;
1183    Evas_Coord mw, mh;
1184
1185    if (inst->popup)
1186      {
1187         e_gadcon_popup_show(inst->popup);
1188         return;
1189      }
1190
1191    inst->popup = e_gadcon_popup_new(inst->gcc);
1192    evas = inst->popup->win->evas;
1193
1194    inst->ui.table = e_widget_table_add(evas, 0);
1195
1196    if (ctxt->default_service)
1197      eina_stringshare_replace(&inst->service_path, ctxt->default_service->path);
1198
1199    // TODO: get this size from edj
1200    inst->ui.list = e_widget_ilist_add(evas, 32, 32, &inst->service_path);
1201    e_widget_size_min_set(inst->ui.list, 180, 100);
1202    e_widget_table_object_append(inst->ui.table, inst->ui.list,
1203                                 0, 0, 1, 5, 1, 1, 1, 1);
1204
1205    inst->offline_mode = ctxt->offline_mode;
1206    inst->ui.offline_mode = e_widget_check_add
1207        (evas, _("Offline mode"), &inst->offline_mode);
1208
1209    evas_object_show(inst->ui.offline_mode);
1210    e_widget_table_object_append(inst->ui.table, inst->ui.offline_mode,
1211                                 0, 5, 1, 1, 1, 1, 1, 0);
1212    e_widget_on_change_hook_set
1213      (inst->ui.offline_mode, _connman_popup_cb_offline_mode_changed, inst);
1214
1215    inst->ui.button = e_widget_button_add
1216        (evas, _("Controls"), NULL,
1217        _connman_popup_cb_controls, inst, NULL);
1218    e_widget_table_object_append(inst->ui.table, inst->ui.button,
1219                                 0, 6, 1, 1, 1, 1, 1, 0);
1220
1221    _connman_popup_update(inst);
1222
1223    e_widget_size_min_get(inst->ui.table, &mw, &mh);
1224    if (mh < 200) mh = 200;
1225    if (mw < 200) mw = 200;
1226    e_widget_size_min_set(inst->ui.table, mw, mh);
1227
1228    e_gadcon_popup_content_set(inst->popup, inst->ui.table);
1229    e_gadcon_popup_show(inst->popup);
1230    _connman_popup_input_window_create(inst);
1231 }
1232
1233 static void
1234 _connman_menu_cb_post(void        *data,
1235                       E_Menu *menu __UNUSED__)
1236 {
1237    E_Connman_Instance *inst = data;
1238    if ((!inst) || (!inst->menu))
1239      return;
1240    if (inst->menu)
1241      {
1242         e_object_del(E_OBJECT(inst->menu));
1243         inst->menu = NULL;
1244      }
1245 }
1246
1247 static void
1248 _connman_menu_cb_cfg(void           *data,
1249                      E_Menu *menu    __UNUSED__,
1250                      E_Menu_Item *mi __UNUSED__)
1251 {
1252    E_Connman_Instance *inst = data;
1253
1254    if (!inst)
1255      return;
1256    if (inst->popup)
1257      _connman_popup_del(inst);
1258    if (inst->ctxt->conf_dialog)
1259      return;
1260
1261    inst->ctxt->conf_dialog = e_connman_config_dialog_new(NULL, inst->ctxt);
1262 }
1263
1264 static void
1265 _connman_menu_new(E_Connman_Instance    *inst,
1266                   Evas_Event_Mouse_Down *ev)
1267 {
1268    E_Zone *zone;
1269    E_Menu *m;
1270    E_Menu_Item *mi;
1271    int x, y;
1272
1273    zone = e_util_zone_current_get(e_manager_current_get());
1274
1275    m = e_menu_new();
1276    mi = e_menu_item_new(m);
1277    e_menu_item_label_set(mi, _("Settings"));
1278    e_util_menu_item_theme_icon_set(mi, "configure");
1279    e_menu_item_callback_set(mi, _connman_menu_cb_cfg, inst);
1280
1281    m = e_gadcon_client_util_menu_items_append(inst->gcc, m, 0);
1282    e_menu_post_deactivate_callback_set(m, _connman_menu_cb_post, inst);
1283    inst->menu = m;
1284    e_gadcon_canvas_zone_geometry_get(inst->gcc->gadcon, &x, &y, NULL, NULL);
1285    e_menu_activate_mouse(m, zone, x + ev->output.x, y + ev->output.y,
1286                          1, 1, E_MENU_POP_DIRECTION_AUTO, ev->timestamp);
1287    evas_event_feed_mouse_up(inst->gcc->gadcon->evas, ev->button,
1288                             EVAS_BUTTON_NONE, ev->timestamp, NULL);
1289 }
1290
1291 static void
1292 _connman_tip_new(E_Connman_Instance *inst)
1293 {
1294    Evas *e;
1295
1296    inst->tip = e_gadcon_popup_new(inst->gcc);
1297    if (!inst->tip) return;
1298
1299    e = inst->tip->win->evas;
1300
1301    inst->o_tip = edje_object_add(e);
1302    e_theme_edje_object_set(inst->o_tip, "base/theme/modules/connman/tip",
1303                            "e/modules/connman/tip");
1304
1305    _connman_tip_update(inst);
1306
1307    e_gadcon_popup_content_set(inst->tip, inst->o_tip);
1308    e_gadcon_popup_show(inst->tip);
1309 }
1310
1311 static void
1312 _connman_tip_del(E_Connman_Instance *inst)
1313 {
1314    evas_object_del(inst->o_tip);
1315    e_object_del(E_OBJECT(inst->tip));
1316    inst->tip = NULL;
1317    inst->o_tip = NULL;
1318 }
1319
1320 static void
1321 _connman_cb_mouse_down(void            *data,
1322                        Evas *evas       __UNUSED__,
1323                        Evas_Object *obj __UNUSED__,
1324                        void            *event)
1325 {
1326    E_Connman_Instance *inst;
1327    Evas_Event_Mouse_Down *ev;
1328
1329    inst = data;
1330    if (!inst)
1331      return;
1332
1333    ev = event;
1334    if (ev->button == 1)
1335      {
1336         if (!inst->popup)
1337           _connman_popup_new(inst);
1338         else
1339           _connman_popup_del(inst);
1340      }
1341    else if (ev->button == 2)
1342      _connman_toggle_offline_mode(inst->ctxt);
1343    else if ((ev->button == 3) && (!inst->menu))
1344      _connman_menu_new(inst, ev);
1345 }
1346
1347 static void
1348 _connman_cb_mouse_in(void            *data,
1349                      Evas *evas       __UNUSED__,
1350                      Evas_Object *obj __UNUSED__,
1351                      void *event      __UNUSED__)
1352 {
1353    E_Connman_Instance *inst = data;
1354
1355    if (inst->tip)
1356      return;
1357
1358    _connman_tip_new(inst);
1359 }
1360
1361 static void
1362 _connman_cb_mouse_out(void            *data,
1363                       Evas *evas       __UNUSED__,
1364                       Evas_Object *obj __UNUSED__,
1365                       void *event      __UNUSED__)
1366 {
1367    E_Connman_Instance *inst = data;
1368
1369    if (!inst->tip)
1370      return;
1371
1372    _connman_tip_del(inst);
1373 }
1374
1375 static void
1376 _connman_edje_view_update(E_Connman_Instance *inst,
1377                           Evas_Object        *o)
1378 {
1379    E_Connman_Module_Context *ctxt = inst->ctxt;
1380    const E_Connman_Service *service;
1381    Edje_Message_Int msg;
1382    char buf[128];
1383
1384    if (!ctxt->has_manager)
1385      {
1386         edje_object_signal_emit(o, "e,unavailable", "e");
1387         edje_object_part_text_set(o, "e.text.name", _("No ConnMan"));
1388         edje_object_part_text_set(o, "e.text.error",
1389                                   _("No ConnMan server found."));
1390         edje_object_signal_emit(o, "e,changed,connected,no", "e");
1391         edje_object_part_text_set(o, "e.text.offline_mode", "");
1392         edje_object_signal_emit(o, "e,changed,offline_mode,no", "e");
1393         return;
1394      }
1395
1396    edje_object_signal_emit(o, "e,available", "e");
1397
1398    if (ctxt->offline_mode)
1399      {
1400         edje_object_signal_emit(o, "e,changed,offline_mode,yes", "e");
1401         edje_object_part_text_set(o, "e.text.offline_mode",
1402                                   _("Offline mode: all radios are turned off"));
1403      }
1404    else
1405      {
1406         edje_object_signal_emit(o, "e,changed,offline_mode,no", "e");
1407         edje_object_part_text_set(o, "e.text.offline_mode", "");
1408      }
1409
1410    if (ctxt->technology && ctxt->technology[0])
1411      {
1412         edje_object_part_text_set(o, "e.text.technology",
1413                                   ctxt->technology);
1414         snprintf(buf, sizeof(buf), "e,changed,technology,%s",
1415                  ctxt->technology);
1416         edje_object_signal_emit(o, buf, "e");
1417      }
1418    else if (!ctxt->default_service)
1419      {
1420         edje_object_part_text_set(o, "e.text.technology", "");
1421         edje_object_signal_emit(o, "e,changed,technology,none", "e");
1422      }
1423
1424    service = ctxt->default_service;
1425    if (!service)
1426      {
1427         edje_object_part_text_set(o, "e.text.name", _("No Connection"));
1428         edje_object_signal_emit(o, "e,changed,service,none", "e");
1429         edje_object_signal_emit(o, "e,changed,connected,no", "e");
1430
1431         edje_object_part_text_set(o, "e.text.error", _("Not connected"));
1432         edje_object_signal_emit(o, "e,changed,error,no", "e");
1433
1434         edje_object_part_text_set(o, "e.text.state", _("disconnect"));
1435         edje_object_signal_emit(o, "e,changed,state,disconnect", "e");
1436
1437         edje_object_signal_emit(o, "e,changed,mode,no", "e");
1438
1439         edje_object_signal_emit(o, "e,changed,mode,none", "e");
1440         edje_object_signal_emit(o, "e,changed,security,none", "e");
1441
1442         edje_object_part_text_set(o, "e.text.ipv4_address", "");
1443         edje_object_signal_emit(o, "e,changed,ipv4_address,no", "e");
1444
1445         edje_object_signal_emit(o, "e,changed,favorite,no", "e");
1446         edje_object_signal_emit(o, "e,changed,auto_connect,no", "e");
1447         edje_object_signal_emit(o, "e,changed,pass_required,no", "e");
1448
1449         return;
1450      }
1451
1452    edje_object_signal_emit(o, "e,changed,connected,yes", "e");
1453
1454    if (service->name)
1455      edje_object_part_text_set(o, "e.text.name", service->name);
1456    else
1457      edje_object_part_text_set(o, "e.text.name", _("Unknown Name"));
1458
1459    if (service->error)
1460      {
1461         edje_object_part_text_set(o, "e.text.error", service->error);
1462         edje_object_signal_emit(o, "e,changed,error,yes", "e");
1463      }
1464    else
1465      {
1466         edje_object_part_text_set(o, "e.text.error", _("No error"));
1467         edje_object_signal_emit(o, "e,changed,error,no", "e");
1468      }
1469
1470    snprintf(buf, sizeof(buf), "e,changed,service,%s", service->type);
1471    edje_object_signal_emit(o, buf, "e");
1472
1473    if (!ctxt->technology)
1474      {
1475         edje_object_part_text_set(o, "e.text.technology", service->type);
1476         snprintf(buf, sizeof(buf), "e,changed,technology,%s", service->type);
1477         edje_object_signal_emit(o, buf, "e");
1478      }
1479
1480    snprintf(buf, sizeof(buf), "e,changed,state,%s", service->state);
1481    edje_object_signal_emit(o, buf, "e");
1482    edje_object_part_text_set(o, "e.text.state", _(service->state));
1483
1484    if (service->mode)
1485      {
1486         snprintf(buf, sizeof(buf), "e,changed,mode,%s", service->mode);
1487         edje_object_signal_emit(o, buf, "e");
1488      }
1489    else
1490      edje_object_signal_emit(o, "e,changed,mode,none", "e");
1491
1492    if (service->security)
1493      {
1494         snprintf(buf, sizeof(buf), "e,changed,security,%s", service->security);
1495         edje_object_signal_emit(o, buf, "e");
1496      }
1497    else
1498      edje_object_signal_emit(o, "e,changed,security,none", "e");
1499
1500    if (service->ipv4_address)
1501      {
1502         edje_object_part_text_set(o, "e.text.ipv4_address", service->ipv4_address);
1503         edje_object_signal_emit(o, "e,changed,ipv4_address,yes", "e");
1504      }
1505    else
1506      {
1507         edje_object_part_text_set(o, "e.text.ipv4_address", "");
1508         edje_object_signal_emit(o, "e,changed,ipv4_address,no", "e");
1509      }
1510
1511    if (service->favorite)
1512      edje_object_signal_emit(o, "e,changed,favorite,yes", "e");
1513    else
1514      edje_object_signal_emit(o, "e,changed,favorite,no", "e");
1515
1516    if (service->auto_connect)
1517      edje_object_signal_emit(o, "e,changed,auto_connect,yes", "e");
1518    else
1519      edje_object_signal_emit(o, "e,changed,auto_connect,no", "e");
1520
1521    if (service->pass_required)
1522      edje_object_signal_emit(o, "e,changed,pass_required,yes", "e");
1523    else
1524      edje_object_signal_emit(o, "e,changed,pass_required,no", "e");
1525
1526    msg.val = service->strength;
1527    edje_object_message_send(o, EDJE_MESSAGE_INT, 1, &msg);
1528 }
1529
1530 static void
1531 _connman_tip_update(E_Connman_Instance *inst)
1532 {
1533    _connman_edje_view_update(inst, inst->o_tip);
1534 }
1535
1536 static void
1537 _connman_gadget_update(E_Connman_Instance *inst)
1538 {
1539    E_Connman_Module_Context *ctxt = inst->ctxt;
1540
1541    if (!ctxt->has_manager && inst->popup)
1542      _connman_popup_del(inst);
1543
1544    if (inst->popup)
1545      _connman_popup_update(inst);
1546    if (inst->tip)
1547      _connman_tip_update(inst);
1548
1549    _connman_edje_view_update(inst, inst->ui.gadget);
1550 }
1551
1552 /* Gadcon Api Functions */
1553
1554 static E_Gadcon_Client *
1555 _gc_init(E_Gadcon   *gc,
1556          const char *name,
1557          const char *id,
1558          const char *style)
1559 {
1560    E_Connman_Instance *inst;
1561    E_Connman_Module_Context *ctxt;
1562
1563    if (!connman_mod)
1564      return NULL;
1565
1566    ctxt = connman_mod->data;
1567
1568    inst = E_NEW(E_Connman_Instance, 1);
1569    inst->ctxt = ctxt;
1570    inst->ui.gadget = edje_object_add(gc->evas);
1571    e_theme_edje_object_set(inst->ui.gadget, "base/theme/modules/connman",
1572                            "e/modules/connman/main");
1573
1574    inst->gcc = e_gadcon_client_new(gc, name, id, style, inst->ui.gadget);
1575    inst->gcc->data = inst;
1576
1577    evas_object_event_callback_add
1578      (inst->ui.gadget, EVAS_CALLBACK_MOUSE_DOWN, _connman_cb_mouse_down, inst);
1579    evas_object_event_callback_add
1580      (inst->ui.gadget, EVAS_CALLBACK_MOUSE_IN, _connman_cb_mouse_in, inst);
1581    evas_object_event_callback_add
1582      (inst->ui.gadget, EVAS_CALLBACK_MOUSE_OUT, _connman_cb_mouse_out, inst);
1583
1584    _connman_gadget_update(inst);
1585
1586    ctxt->instances = eina_list_append(ctxt->instances, inst);
1587
1588    return inst->gcc;
1589 }
1590
1591 static void
1592 _gc_shutdown(E_Gadcon_Client *gcc)
1593 {
1594    E_Connman_Module_Context *ctxt;
1595    E_Connman_Instance *inst;
1596
1597    if (!connman_mod)
1598      return;
1599
1600    ctxt = connman_mod->data;
1601    if (!ctxt)
1602      return;
1603
1604    inst = gcc->data;
1605    if (!inst)
1606      return;
1607
1608    if (inst->menu)
1609      {
1610         e_menu_post_deactivate_callback_set(inst->menu, NULL, NULL);
1611         e_object_del(E_OBJECT(inst->menu));
1612      }
1613    evas_object_del(inst->ui.gadget);
1614
1615    ctxt->instances = eina_list_remove(ctxt->instances, inst);
1616
1617    E_FREE(inst);
1618 }
1619
1620 static void
1621 _gc_orient(E_Gadcon_Client       *gcc,
1622            E_Gadcon_Orient orient __UNUSED__)
1623 {
1624    e_gadcon_client_aspect_set(gcc, 16, 16);
1625    e_gadcon_client_min_size_set(gcc, 16, 16);
1626 }
1627
1628 static char *
1629 _gc_label(E_Gadcon_Client_Class *client_class __UNUSED__)
1630 {
1631    return _(_e_connman_Name);
1632 }
1633
1634 static Evas_Object *
1635 _gc_icon(E_Gadcon_Client_Class *client_class __UNUSED__,
1636          Evas                               *evas)
1637 {
1638    Evas_Object *o;
1639
1640    o = edje_object_add(evas);
1641    edje_object_file_set(o, e_connman_theme_path(), "icon");
1642    return o;
1643 }
1644
1645 static const char *
1646 _gc_id_new(E_Gadcon_Client_Class *client_class __UNUSED__)
1647 {
1648    E_Connman_Module_Context *ctxt;
1649    Eina_List *instances;
1650
1651    if (!connman_mod)
1652      return NULL;
1653
1654    ctxt = connman_mod->data;
1655    if (!ctxt)
1656      return NULL;
1657
1658    instances = ctxt->instances;
1659    snprintf(tmpbuf, sizeof(tmpbuf), "connman.%d", eina_list_count(instances));
1660    return tmpbuf;
1661 }
1662
1663 static const E_Gadcon_Client_Class _gc_class =
1664 {
1665    GADCON_CLIENT_CLASS_VERSION, _e_connman_name,
1666    {
1667       _gc_init, _gc_shutdown, _gc_orient, _gc_label, _gc_icon, _gc_id_new, NULL,
1668       e_gadcon_site_is_not_toolbar
1669    },
1670    E_GADCON_CLIENT_STYLE_PLAIN
1671 };
1672
1673 EAPI E_Module_Api e_modapi = {E_MODULE_API_VERSION, _e_connman_Name};
1674
1675 static const char _act_toggle_offline_mode[] = "toggle_offline_mode";
1676 static const char _lbl_toggle_offline_mode[] = "Toggle Offline Mode";
1677
1678 static void
1679 _connman_actions_register(E_Connman_Module_Context *ctxt)
1680 {
1681    ctxt->actions.toggle_offline_mode = e_action_add(_act_toggle_offline_mode);
1682    if (ctxt->actions.toggle_offline_mode)
1683      {
1684         ctxt->actions.toggle_offline_mode->func.go =
1685           _connman_cb_toggle_offline_mode;
1686         e_action_predef_name_set
1687           (_(_e_connman_Name), _(_lbl_toggle_offline_mode), _act_toggle_offline_mode,
1688           NULL, NULL, 0);
1689      }
1690 }
1691
1692 static void
1693 _connman_actions_unregister(E_Connman_Module_Context *ctxt)
1694 {
1695    if (ctxt->actions.toggle_offline_mode)
1696      {
1697         e_action_predef_name_del(_(_e_connman_Name), _(_lbl_toggle_offline_mode));
1698         e_action_del(_act_toggle_offline_mode);
1699      }
1700 }
1701
1702 static Eina_Bool
1703 _connman_manager_changed_do(void *data)
1704 {
1705    E_Connman_Module_Context *ctxt = data;
1706
1707    _connman_technologies_load(ctxt);
1708    _connman_services_reload(ctxt);
1709
1710    ctxt->poller.manager_changed = NULL;
1711    return ECORE_CALLBACK_CANCEL;
1712 }
1713
1714 static void
1715 _connman_manager_changed(void                            *data,
1716                          const E_Connman_Element *element __UNUSED__)
1717 {
1718    E_Connman_Module_Context *ctxt = data;
1719    if (ctxt->poller.manager_changed)
1720      ecore_poller_del(ctxt->poller.manager_changed);
1721    ctxt->poller.manager_changed = ecore_poller_add
1722        (ECORE_POLLER_CORE, 1, _connman_manager_changed_do, ctxt);
1723 }
1724
1725 static Eina_Bool
1726 _connman_event_manager_in(void       *data,
1727                           int type    __UNUSED__,
1728                           void *event __UNUSED__)
1729 {
1730    E_Connman_Module_Context *ctxt = data;
1731    E_Connman_Element *element;
1732
1733    ctxt->has_manager = EINA_TRUE;
1734
1735    element = e_connman_manager_get();
1736    e_connman_element_listener_add
1737      (element, _connman_manager_changed, ctxt, NULL);
1738
1739    _connman_services_reload(ctxt);
1740
1741    return ECORE_CALLBACK_PASS_ON;
1742 }
1743
1744 static Eina_Bool
1745 _connman_event_manager_out(void       *data,
1746                            int type    __UNUSED__,
1747                            void *event __UNUSED__)
1748 {
1749    E_Connman_Module_Context *ctxt = data;
1750
1751    ctxt->has_manager = EINA_FALSE;
1752    eina_stringshare_replace(&ctxt->technology, NULL);
1753
1754    _connman_services_free(ctxt);
1755    _connman_default_service_changed(ctxt);
1756
1757    return ECORE_CALLBACK_PASS_ON;
1758 }
1759
1760 static Eina_Bool
1761 _connman_event_mode_changed(void       *data,
1762                             int type    __UNUSED__,
1763                             void *event __UNUSED__)
1764 {
1765    E_Connman_Module_Context *ctxt = data;
1766    if ((ctxt->offline_mode == e_config->mode.offline) ||
1767        (!ctxt->has_manager))
1768      return ECORE_CALLBACK_PASS_ON;
1769    if (!ctxt->offline_mode_pending)
1770      {
1771         if (!e_connman_manager_offline_mode_set(e_config->mode.offline,
1772                                                 _connman_toggle_offline_mode_cb, ctxt))
1773           _connman_operation_error_show(_("Cannot toggle system's offline mode."));
1774      }
1775    else
1776      ctxt->offline_mode_pending = EINA_FALSE;
1777
1778    return ECORE_CALLBACK_PASS_ON;
1779 }
1780
1781 static E_Config_Dialog *
1782 _connman_config(E_Container       *con,
1783                 const char *params __UNUSED__)
1784 {
1785    E_Connman_Module_Context *ctxt;
1786
1787    if (!connman_mod)
1788      return NULL;
1789
1790    ctxt = connman_mod->data;
1791    if (!ctxt)
1792      return NULL;
1793
1794    if (!ctxt->conf_dialog)
1795      ctxt->conf_dialog = e_connman_config_dialog_new(con, ctxt);
1796
1797    return ctxt->conf_dialog;
1798 }
1799
1800 static const char _reg_cat[] = "extensions";
1801 static const char _reg_item[] = "extensions/connman";
1802
1803 static void
1804 _connman_configure_registry_register(void)
1805 {
1806    e_configure_registry_category_add(_reg_cat, 90, _("Extensions"), NULL,
1807                                      "preferences-extensions");
1808    e_configure_registry_item_add(_reg_item, 110, _(_e_connman_Name), NULL,
1809                                  e_connman_theme_path(),
1810                                  _connman_config);
1811 }
1812
1813 static void
1814 _connman_configure_registry_unregister(void)
1815 {
1816    e_configure_registry_item_del(_reg_item);
1817    e_configure_registry_category_del(_reg_cat);
1818 }
1819
1820 static void
1821 _connman_events_register(E_Connman_Module_Context *ctxt)
1822 {
1823    ctxt->event.manager_in = ecore_event_handler_add
1824        (E_CONNMAN_EVENT_MANAGER_IN, _connman_event_manager_in, ctxt);
1825    ctxt->event.manager_out = ecore_event_handler_add
1826        (E_CONNMAN_EVENT_MANAGER_OUT, _connman_event_manager_out, ctxt);
1827    ctxt->event.mode_changed = ecore_event_handler_add
1828        (E_EVENT_CONFIG_MODE_CHANGED, _connman_event_mode_changed, ctxt);
1829 }
1830
1831 static void
1832 _connman_events_unregister(E_Connman_Module_Context *ctxt)
1833 {
1834    if (ctxt->event.manager_in)
1835      ecore_event_handler_del(ctxt->event.manager_in);
1836    if (ctxt->event.manager_out)
1837      ecore_event_handler_del(ctxt->event.manager_out);
1838    if (ctxt->event.mode_changed)
1839      ecore_event_handler_del(ctxt->event.mode_changed);
1840 }
1841
1842 static inline void
1843 _connman_status_stringshare_init(void)
1844 {
1845    e_str_idle = eina_stringshare_add(N_("idle"));
1846    e_str_association = eina_stringshare_add(N_("association"));
1847    e_str_configuration = eina_stringshare_add(N_("configuration"));
1848    e_str_ready = eina_stringshare_add(N_("ready"));
1849    e_str_login = eina_stringshare_add(N_("login"));
1850    e_str_online = eina_stringshare_add(N_("online"));
1851    e_str_disconnect = eina_stringshare_add(N_("disconnect"));
1852    e_str_failure = eina_stringshare_add(N_("failure"));
1853    e_str_enabled = eina_stringshare_add(N_("enabled"));
1854    e_str_available = eina_stringshare_add(N_("available"));
1855    e_str_connected = eina_stringshare_add(N_("connected"));
1856    e_str_offline = eina_stringshare_add(N_("offline"));
1857 }
1858
1859 static inline void
1860 _connman_status_stringshare_del(void)
1861 {
1862    eina_stringshare_replace(&e_str_idle, NULL);
1863    eina_stringshare_replace(&e_str_association, NULL);
1864    eina_stringshare_replace(&e_str_configuration, NULL);
1865    eina_stringshare_replace(&e_str_ready, NULL);
1866    eina_stringshare_replace(&e_str_login, NULL);
1867    eina_stringshare_replace(&e_str_online, NULL);
1868    eina_stringshare_replace(&e_str_disconnect, NULL);
1869    eina_stringshare_replace(&e_str_failure, NULL);
1870    eina_stringshare_replace(&e_str_enabled, NULL);
1871    eina_stringshare_replace(&e_str_available, NULL);
1872    eina_stringshare_replace(&e_str_connected, NULL);
1873    eina_stringshare_replace(&e_str_offline, NULL);
1874 }
1875
1876 EAPI void *
1877 e_modapi_init(E_Module *m)
1878 {
1879    E_Connman_Module_Context *ctxt;
1880    E_DBus_Connection *c;
1881
1882    _connman_status_stringshare_init();
1883
1884    c = e_dbus_bus_get(DBUS_BUS_SYSTEM);
1885    if (!c)
1886      goto error_dbus_bus_get;
1887    if (!e_connman_system_init(c))
1888      goto error_connman_system_init;
1889
1890    ctxt = E_NEW(E_Connman_Module_Context, 1);
1891    if (!ctxt)
1892      goto error_connman_context;
1893
1894    ctxt->services = NULL;
1895    ctxt->technologies = NULL;
1896    ctxt->conf_dialog = NULL;
1897    connman_mod = m;
1898
1899    if (_e_connman_log_dom < 0)
1900      {
1901         _e_connman_log_dom = eina_log_domain_register("econnman", EINA_COLOR_ORANGE);
1902         if (_e_connman_log_dom < 0)
1903           {
1904              EINA_LOG_CRIT("could not register logging domain econnman");
1905              goto error_log_domain;
1906           }
1907      }
1908
1909    _connman_configure_registry_register();
1910    _connman_actions_register(ctxt);
1911    e_gadcon_provider_register(&_gc_class);
1912
1913    _connman_events_register(ctxt);
1914
1915    return ctxt;
1916
1917 error_log_domain:
1918    _e_connman_log_dom = -1;
1919    connman_mod = NULL;
1920    E_FREE(ctxt);
1921 error_connman_context:
1922    e_connman_system_shutdown();
1923 error_connman_system_init:
1924 error_dbus_bus_get:
1925    _connman_status_stringshare_del();
1926    return NULL;
1927 }
1928
1929 static void
1930 _connman_instances_free(E_Connman_Module_Context *ctxt)
1931 {
1932    while (ctxt->instances)
1933      {
1934         E_Connman_Instance *inst;
1935
1936         inst = ctxt->instances->data;
1937
1938         if (inst->popup)
1939           _connman_popup_del(inst);
1940         if (inst->tip)
1941           _connman_tip_del(inst);
1942
1943         e_object_del(E_OBJECT(inst->gcc));
1944      }
1945 }
1946
1947 EAPI int
1948 e_modapi_shutdown(E_Module *m)
1949 {
1950    E_Connman_Module_Context *ctxt;
1951    E_Connman_Element *element;
1952
1953    ctxt = m->data;
1954    if (!ctxt)
1955      return 0;
1956
1957    element = e_connman_manager_get();
1958    e_connman_element_listener_del
1959      (element, _connman_manager_changed, ctxt);
1960
1961    _connman_events_unregister(ctxt);
1962
1963    _connman_instances_free(ctxt);
1964    _connman_services_free(ctxt);
1965
1966    _connman_configure_registry_unregister();
1967    _connman_actions_unregister(ctxt);
1968    e_gadcon_provider_unregister(&_gc_class);
1969
1970    if (ctxt->poller.default_service_changed)
1971      ecore_poller_del(ctxt->poller.default_service_changed);
1972    if (ctxt->poller.manager_changed)
1973      ecore_poller_del(ctxt->poller.manager_changed);
1974
1975    E_FREE(ctxt);
1976    connman_mod = NULL;
1977
1978    e_connman_system_shutdown();
1979
1980    _connman_status_stringshare_del();
1981    return 1;
1982 }
1983
1984 EAPI int
1985 e_modapi_save(E_Module *m)
1986 {
1987    E_Connman_Module_Context *ctxt;
1988
1989    ctxt = m->data;
1990    if (!ctxt)
1991      return 0;
1992    return 1;
1993 }
1994