]> rtime.felk.cvut.cz Git - sojka/lightdm.git/blob - greeters/ldm-webkit-greeter.c
Add configuration for default language/layout
[sojka/lightdm.git] / greeters / ldm-webkit-greeter.c
1 /*
2  * Copyright (C) 2010 Robert Ancell.
3  * Author: Robert Ancell <robert.ancell@canonical.com>
4  *
5  * This program is free software: you can redistribute it and/or modify it under
6  * the terms of the GNU General Public License as published by the Free Software
7  * Foundation, either version 3 of the License, or (at your option) any later
8  * version. See http://www.gnu.org/copyleft/gpl.html the full text of the
9  * license.
10  */
11
12 #include <stdlib.h>
13 #include <gtk/gtk.h>
14 #include <webkit/webkit.h>
15 #include <JavaScriptCore/JavaScript.h>
16 #include <glib/gi18n.h>
17
18 #include "greeter.h"
19
20 static JSClassRef gettext_class, ldm_greeter_class, ldm_user_class, ldm_language_class, ldm_layout_class, ldm_session_class;
21
22 static GtkWidget *window;
23
24 static void
25 show_prompt_cb (LdmGreeter *greeter, const gchar *text, WebKitWebView *view)
26 {
27     gchar *command;
28
29     command = g_strdup_printf ("show_prompt('%s')", text); // FIXME: Escape text
30     webkit_web_view_execute_script (view, command);
31     g_free (command);
32 }
33
34 static void
35 show_message_cb (LdmGreeter *greeter, const gchar *text, WebKitWebView *view)
36 {
37     gchar *command;
38
39     command = g_strdup_printf ("show_message('%s')", text); // FIXME: Escape text
40     webkit_web_view_execute_script (view, command);
41     g_free (command);
42 }
43
44 static void
45 authentication_complete_cb (LdmGreeter *greeter, WebKitWebView *view)
46 {
47     webkit_web_view_execute_script (view, "authentication_complete()");
48 }
49
50 static void
51 timed_login_cb (LdmGreeter *greeter, const gchar *username, WebKitWebView *view)
52 {
53     gchar *command;
54
55     command = g_strdup_printf ("timed_login('%s')", username); // FIXME: Escape text
56     webkit_web_view_execute_script (view, command);
57     g_free (command);
58 }
59
60 static gboolean
61 fade_timer_cb (gpointer data)
62 {
63     gdouble opacity;
64
65     opacity = gtk_window_get_opacity (GTK_WINDOW (window));
66     opacity -= 0.1;
67     if (opacity <= 0)
68     {
69         gtk_main_quit ();
70         return FALSE;
71     }
72     gtk_window_set_opacity (GTK_WINDOW (window), opacity);
73
74     return TRUE;
75 }
76
77 static void
78 quit_cb (LdmGreeter *greeter, const gchar *username)
79 {
80     /* Fade out the greeter */
81     g_timeout_add (40, (GSourceFunc) fade_timer_cb, NULL);
82 }
83
84 static JSValueRef
85 get_user_name_cb (JSContextRef context,
86                   JSObjectRef thisObject,
87                   JSStringRef propertyName,
88                   JSValueRef *exception)
89 {
90     LdmUser *user = JSObjectGetPrivate (thisObject);
91     JSStringRef string;
92
93     string = JSStringCreateWithUTF8CString (ldm_user_get_name (user));
94     return JSValueMakeString (context, string);
95 }
96
97 static JSValueRef
98 get_user_real_name_cb (JSContextRef context,
99                        JSObjectRef thisObject,
100                        JSStringRef propertyName,
101                        JSValueRef *exception)
102 {
103     LdmUser *user = JSObjectGetPrivate (thisObject);
104     JSStringRef string;
105
106     string = JSStringCreateWithUTF8CString (ldm_user_get_real_name (user));
107     return JSValueMakeString (context, string);
108 }
109
110 static JSValueRef
111 get_user_display_name_cb (JSContextRef context,
112                           JSObjectRef thisObject,
113                           JSStringRef propertyName,
114                           JSValueRef *exception)
115 {
116     LdmUser *user = JSObjectGetPrivate (thisObject);
117     JSStringRef string;
118
119     string = JSStringCreateWithUTF8CString (ldm_user_get_display_name (user));
120     return JSValueMakeString (context, string);
121 }
122
123 static JSValueRef
124 get_user_image_cb (JSContextRef context,
125                    JSObjectRef thisObject,
126                    JSStringRef propertyName,
127                    JSValueRef *exception)
128 {
129     LdmUser *user = JSObjectGetPrivate (thisObject);
130     JSStringRef string;
131
132     string = JSStringCreateWithUTF8CString (ldm_user_get_image (user));
133     return JSValueMakeString (context, string);
134 }
135
136 static JSValueRef
137 get_user_logged_in_cb (JSContextRef context,
138                        JSObjectRef thisObject,
139                        JSStringRef propertyName,
140                        JSValueRef *exception)
141 {
142     LdmUser *user = JSObjectGetPrivate (thisObject);
143     return JSValueMakeBoolean (context, ldm_user_get_logged_in (user));
144 }
145
146 static JSValueRef
147 get_language_code_cb (JSContextRef context,
148                       JSObjectRef thisObject,
149                       JSStringRef propertyName,
150                       JSValueRef *exception)
151 {
152     LdmLanguage *language = JSObjectGetPrivate (thisObject);
153     JSStringRef string;
154
155     string = JSStringCreateWithUTF8CString (ldm_language_get_code (language));
156     return JSValueMakeString (context, string);
157 }
158
159 static JSValueRef
160 get_language_name_cb (JSContextRef context,
161                       JSObjectRef thisObject,
162                       JSStringRef propertyName,
163                       JSValueRef *exception)
164 {
165     LdmLanguage *language = JSObjectGetPrivate (thisObject);
166     JSStringRef string;
167
168     string = JSStringCreateWithUTF8CString (ldm_language_get_name (language));
169     return JSValueMakeString (context, string);
170 }
171
172 static JSValueRef
173 get_language_territory_cb (JSContextRef context,
174                            JSObjectRef thisObject,
175                            JSStringRef propertyName,
176                            JSValueRef *exception)
177 {
178     LdmLanguage *language = JSObjectGetPrivate (thisObject);
179     JSStringRef string;
180
181     string = JSStringCreateWithUTF8CString (ldm_language_get_territory (language));
182     return JSValueMakeString (context, string);
183 }
184
185 static JSValueRef
186 get_layout_name_cb (JSContextRef context,
187                     JSObjectRef thisObject,
188                     JSStringRef propertyName,
189                     JSValueRef *exception)
190 {
191     LdmLayout *layout = JSObjectGetPrivate (thisObject);
192     JSStringRef string;
193
194     string = JSStringCreateWithUTF8CString (ldm_layout_get_name (layout));
195     return JSValueMakeString (context, string);
196 }
197
198 static JSValueRef
199 get_layout_short_description_cb (JSContextRef context,
200                                  JSObjectRef thisObject,
201                                  JSStringRef propertyName,
202                                  JSValueRef *exception)
203 {
204     LdmLayout *layout = JSObjectGetPrivate (thisObject);
205     JSStringRef string;
206
207     string = JSStringCreateWithUTF8CString (ldm_layout_get_short_description (layout));
208     return JSValueMakeString (context, string);
209 }
210
211 static JSValueRef
212 get_layout_description_cb (JSContextRef context,
213                            JSObjectRef thisObject,
214                            JSStringRef propertyName,
215                            JSValueRef *exception)
216 {
217     LdmLayout *layout = JSObjectGetPrivate (thisObject);
218     JSStringRef string;
219
220     string = JSStringCreateWithUTF8CString (ldm_layout_get_description (layout));
221     return JSValueMakeString (context, string);
222 }
223
224 static JSValueRef
225 get_session_key_cb (JSContextRef context,
226                     JSObjectRef thisObject,
227                     JSStringRef propertyName,
228                     JSValueRef *exception)
229 {
230     LdmSession *session = JSObjectGetPrivate (thisObject);
231     JSStringRef string;
232
233     string = JSStringCreateWithUTF8CString (ldm_session_get_key (session));
234     return JSValueMakeString (context, string);
235
236 }
237 static JSValueRef
238 get_session_name_cb (JSContextRef context,
239                      JSObjectRef thisObject,
240                      JSStringRef propertyName,
241                      JSValueRef *exception)
242 {
243     LdmSession *session = JSObjectGetPrivate (thisObject);
244     JSStringRef string;
245
246     string = JSStringCreateWithUTF8CString (ldm_session_get_name (session));
247     return JSValueMakeString (context, string);
248 }
249
250 static JSValueRef
251 get_session_comment_cb (JSContextRef context,
252                         JSObjectRef thisObject,
253                         JSStringRef propertyName,
254                         JSValueRef *exception)
255 {
256     LdmSession *session = JSObjectGetPrivate (thisObject);
257     JSStringRef string;
258
259     string = JSStringCreateWithUTF8CString (ldm_session_get_comment (session));
260     return JSValueMakeString (context, string);
261 }
262
263 static JSValueRef
264 get_hostname_cb (JSContextRef context,
265                  JSObjectRef thisObject,
266                  JSStringRef propertyName,
267                  JSValueRef *exception)
268 {
269     LdmGreeter *greeter = JSObjectGetPrivate (thisObject);
270     JSStringRef string;
271
272     string = JSStringCreateWithUTF8CString (ldm_greeter_get_hostname (greeter));
273
274     return JSValueMakeString (context, string);
275 }
276
277 static JSValueRef
278 get_num_users_cb (JSContextRef context,
279                   JSObjectRef thisObject,
280                   JSStringRef propertyName,
281                   JSValueRef *exception)
282 {
283     LdmGreeter *greeter = JSObjectGetPrivate (thisObject);
284     gint num_users;
285
286     num_users = ldm_greeter_get_num_users (greeter);
287     return JSValueMakeNumber (context, num_users);
288 }
289
290 static JSValueRef
291 get_users_cb (JSContextRef context,
292               JSObjectRef thisObject,
293               JSStringRef propertyName,
294               JSValueRef *exception)
295 {
296     LdmGreeter *greeter = JSObjectGetPrivate (thisObject);
297     JSObjectRef array;
298     const GList *users, *link;
299     guint i, n_users = 0;
300     JSValueRef *args;
301
302     users = ldm_greeter_get_users (greeter);
303     n_users = g_list_length ((GList *)users);
304     args = g_malloc (sizeof (JSValueRef) * (n_users + 1));
305     for (i = 0, link = users; link; i++, link = link->next)
306     {
307         LdmUser *user = link->data;
308         g_object_ref (user);
309         args[i] = JSObjectMake (context, ldm_user_class, user);
310     }
311
312     array = JSObjectMakeArray (context, n_users, args, NULL);
313     g_free (args);
314     return array;
315 }
316
317 static JSValueRef
318 get_languages_cb (JSContextRef context,
319                   JSObjectRef thisObject,
320                   JSStringRef propertyName,
321                   JSValueRef *exception)
322 {
323     LdmGreeter *greeter = JSObjectGetPrivate (thisObject);
324     JSObjectRef array;
325     const GList *languages, *link;
326     guint i, n_languages = 0;
327     JSValueRef *args;
328
329     languages = ldm_greeter_get_languages (greeter);
330     n_languages = g_list_length ((GList *)languages);
331     args = g_malloc (sizeof (JSValueRef) * (n_languages + 1));
332     for (i = 0, link = languages; link; i++, link = link->next)
333     {
334         LdmLanguage *language = link->data;
335         g_object_ref (language);
336         args[i] = JSObjectMake (context, ldm_language_class, language);
337     }
338
339     array = JSObjectMakeArray (context, n_languages, args, NULL);
340     g_free (args);
341     return array;
342 }
343
344 static JSValueRef
345 get_default_language_cb (JSContextRef context,
346                          JSObjectRef thisObject,
347                          JSStringRef propertyName,
348                          JSValueRef *exception)
349 {
350     LdmGreeter *greeter = JSObjectGetPrivate (thisObject);
351     JSStringRef string;
352
353     string = JSStringCreateWithUTF8CString (ldm_greeter_get_default_language (greeter));
354
355     return JSValueMakeString (context, string);
356 }
357
358 static JSValueRef
359 get_default_layout_cb (JSContextRef context,
360                        JSObjectRef thisObject,
361                        JSStringRef propertyName,
362                        JSValueRef *exception)
363 {
364     LdmGreeter *greeter = JSObjectGetPrivate (thisObject);
365     JSStringRef string;
366
367     string = JSStringCreateWithUTF8CString (ldm_greeter_get_default_layout (greeter));
368
369     return JSValueMakeString (context, string);
370 }
371
372 static JSValueRef
373 get_layouts_cb (JSContextRef context,
374                 JSObjectRef thisObject,
375                 JSStringRef propertyName,
376                 JSValueRef *exception)
377 {
378     LdmGreeter *greeter = JSObjectGetPrivate (thisObject);
379     JSObjectRef array;
380     const GList *layouts, *link;
381     guint i, n_layouts = 0;
382     JSValueRef *args;
383
384     layouts = ldm_greeter_get_layouts (greeter);
385     n_layouts = g_list_length ((GList *)layouts);
386     args = g_malloc (sizeof (JSValueRef) * (n_layouts + 1));
387     for (i = 0, link = layouts; link; i++, link = link->next)
388     {
389         LdmLayout *layout = link->data;
390         g_object_ref (layout);
391         args[i] = JSObjectMake (context, ldm_layout_class, layout);
392     }
393
394     array = JSObjectMakeArray (context, n_layouts, args, NULL);
395     g_free (args);
396     return array;
397 }
398
399 static JSValueRef
400 get_layout_cb (JSContextRef context,
401                JSObjectRef thisObject,
402                JSStringRef propertyName,
403                JSValueRef *exception)
404 {
405     LdmGreeter *greeter = JSObjectGetPrivate (thisObject);
406     JSStringRef string;
407
408     string = JSStringCreateWithUTF8CString (ldm_greeter_get_layout (greeter));
409
410     return JSValueMakeString (context, string);
411 }
412
413 static bool
414 set_layout_cb (JSContextRef context,
415                JSObjectRef thisObject,
416                JSStringRef propertyName,
417                JSValueRef value,
418                JSValueRef *exception)
419 {
420     LdmGreeter *greeter = JSObjectGetPrivate (thisObject);
421     JSStringRef layout_arg;
422     char layout[1024];
423
424     // FIXME: Throw exception
425     if (JSValueGetType (context, value) != kJSTypeString)
426         return false;
427
428     layout_arg = JSValueToStringCopy (context, value, NULL);
429     JSStringGetUTF8CString (layout_arg, layout, 1024);
430     JSStringRelease (layout_arg);
431
432     ldm_greeter_set_layout (greeter, layout);
433
434     return true;
435 }
436
437 static JSValueRef
438 get_sessions_cb (JSContextRef context,
439                  JSObjectRef thisObject,
440                  JSStringRef propertyName,
441                  JSValueRef *exception)
442 {
443     LdmGreeter *greeter = JSObjectGetPrivate (thisObject);
444     JSObjectRef array;
445     const GList *sessions, *link;
446     guint i, n_sessions = 0;
447     JSValueRef *args;
448
449     sessions = ldm_greeter_get_sessions (greeter);
450     n_sessions = g_list_length ((GList *)sessions);
451     args = g_malloc (sizeof (JSValueRef) * (n_sessions + 1));
452     for (i = 0, link = sessions; link; i++, link = link->next)
453     {
454         LdmSession *session = link->data;
455         g_object_ref (session);
456         args[i] = JSObjectMake (context, ldm_session_class, session);
457     }
458
459     array = JSObjectMakeArray (context, n_sessions, args, NULL);
460     g_free (args);
461     return array;
462 }
463
464 static JSValueRef
465 get_default_session_cb (JSContextRef context,
466                         JSObjectRef thisObject,
467                         JSStringRef propertyName,
468                         JSValueRef *exception)
469 {
470     LdmGreeter *greeter = JSObjectGetPrivate (thisObject);
471     JSStringRef string;
472
473     string = JSStringCreateWithUTF8CString (ldm_greeter_get_default_session (greeter));
474
475     return JSValueMakeString (context, string);
476 }
477
478 static JSValueRef
479 get_timed_login_user_cb (JSContextRef context,
480                          JSObjectRef thisObject,
481                          JSStringRef propertyName,
482                          JSValueRef *exception)
483 {
484     LdmGreeter *greeter = JSObjectGetPrivate (thisObject);
485     JSStringRef string;
486
487     string = JSStringCreateWithUTF8CString (ldm_greeter_get_timed_login_user (greeter));
488
489     return JSValueMakeString (context, string);
490 }
491
492 static JSValueRef
493 get_timed_login_delay_cb (JSContextRef context,
494                           JSObjectRef thisObject,
495                           JSStringRef propertyName,
496                           JSValueRef *exception)
497 {
498     LdmGreeter *greeter = JSObjectGetPrivate (thisObject);
499     gint delay;
500
501     delay = ldm_greeter_get_timed_login_delay (greeter);
502     return JSValueMakeNumber (context, delay);
503 }
504
505 static JSValueRef
506 get_string_property_cb (JSContextRef context,
507                         JSObjectRef function,
508                         JSObjectRef thisObject,
509                         size_t argumentCount,
510                         const JSValueRef arguments[],
511                         JSValueRef *exception)
512 {
513     LdmGreeter *greeter = JSObjectGetPrivate (thisObject);
514     JSStringRef name_arg;
515     char name[1024];
516     gchar *value;
517     JSStringRef string;
518
519     // FIXME: Throw exception
520     if (argumentCount != 1)
521         return JSValueMakeNull (context);
522
523     name_arg = JSValueToStringCopy (context, arguments[0], NULL);
524     JSStringGetUTF8CString (name_arg, name, 1024);
525     JSStringRelease (name_arg);
526
527     value = ldm_greeter_get_string_property (greeter, name);
528
529     if (!value)
530         return JSValueMakeNull (context);
531
532     string = JSStringCreateWithUTF8CString (value);
533     g_free (value);
534     return JSValueMakeString (context, string);
535 }
536
537 static JSValueRef
538 get_integer_property_cb (JSContextRef context,
539                          JSObjectRef function,
540                          JSObjectRef thisObject,
541                          size_t argumentCount,
542                          const JSValueRef arguments[],
543                          JSValueRef *exception)
544 {
545     LdmGreeter *greeter = JSObjectGetPrivate (thisObject);
546     JSStringRef name_arg;
547     char name[1024];
548
549     // FIXME: Throw exception
550     if (argumentCount != 1)
551         return JSValueMakeNull (context);
552
553     name_arg = JSValueToStringCopy (context, arguments[0], NULL);
554     JSStringGetUTF8CString (name_arg, name, 1024);
555     JSStringRelease (name_arg);
556
557     return JSValueMakeNumber (context, ldm_greeter_get_integer_property (greeter, name));
558 }
559
560 static JSValueRef
561 get_boolean_property_cb (JSContextRef context,
562                          JSObjectRef function,
563                          JSObjectRef thisObject,
564                          size_t argumentCount,
565                          const JSValueRef arguments[],
566                          JSValueRef *exception)
567 {
568     LdmGreeter *greeter = JSObjectGetPrivate (thisObject);
569     JSStringRef name_arg;
570     char name[1024];
571
572     // FIXME: Throw exception
573     if (argumentCount != 1)
574         return JSValueMakeNull (context);
575
576     name_arg = JSValueToStringCopy (context, arguments[0], NULL);
577     JSStringGetUTF8CString (name_arg, name, 1024);
578     JSStringRelease (name_arg);
579
580     return JSValueMakeBoolean (context, ldm_greeter_get_boolean_property (greeter, name));
581 }
582
583 static JSValueRef
584 cancel_timed_login_cb (JSContextRef context,
585                        JSObjectRef function,
586                        JSObjectRef thisObject,
587                        size_t argumentCount,
588                        const JSValueRef arguments[],
589                        JSValueRef *exception)
590 {
591     LdmGreeter *greeter = JSObjectGetPrivate (thisObject);
592
593     // FIXME: Throw exception
594     if (argumentCount != 0)
595         return JSValueMakeNull (context);
596
597     ldm_greeter_cancel_timed_login (greeter);
598     return JSValueMakeNull (context);
599 }
600
601 static JSValueRef
602 start_authentication_cb (JSContextRef context,
603                          JSObjectRef function,
604                          JSObjectRef thisObject,
605                          size_t argumentCount,
606                          const JSValueRef arguments[],
607                          JSValueRef *exception)
608 {
609     LdmGreeter *greeter = JSObjectGetPrivate (thisObject);
610     JSStringRef name_arg;
611     char name[1024];
612
613     // FIXME: Throw exception
614     if (!(argumentCount == 1 && JSValueGetType (context, arguments[0]) == kJSTypeString))
615         return JSValueMakeNull (context);
616
617     name_arg = JSValueToStringCopy (context, arguments[0], NULL);
618     JSStringGetUTF8CString (name_arg, name, 1024);
619     JSStringRelease (name_arg);
620
621     ldm_greeter_start_authentication (greeter, name);
622     return JSValueMakeNull (context);
623 }
624
625 static JSValueRef
626 provide_secret_cb (JSContextRef context,
627                    JSObjectRef function,
628                    JSObjectRef thisObject,
629                    size_t argumentCount,
630                    const JSValueRef arguments[],
631                    JSValueRef *exception)
632 {
633     LdmGreeter *greeter = JSObjectGetPrivate (thisObject);
634     JSStringRef secret_arg;
635     char secret[1024];
636
637     // FIXME: Throw exception
638     if (!(argumentCount == 1 && JSValueGetType (context, arguments[0]) == kJSTypeString))
639         return JSValueMakeNull (context);
640
641     secret_arg = JSValueToStringCopy (context, arguments[0], NULL);
642     JSStringGetUTF8CString (secret_arg, secret, 1024);
643     JSStringRelease (secret_arg);
644
645     ldm_greeter_provide_secret (greeter, secret);
646     return JSValueMakeNull (context);
647 }
648
649 static JSValueRef
650 cancel_authentication_cb (JSContextRef context,
651                           JSObjectRef function,
652                           JSObjectRef thisObject,
653                           size_t argumentCount,
654                           const JSValueRef arguments[],
655                           JSValueRef *exception)
656 {
657     LdmGreeter *greeter = JSObjectGetPrivate (thisObject);
658
659     // FIXME: Throw exception
660     if (argumentCount != 0)
661         return JSValueMakeNull (context);
662
663     ldm_greeter_cancel_authentication (greeter);
664     return JSValueMakeNull (context);
665 }
666
667 static JSValueRef
668 get_authentication_user_cb (JSContextRef context,
669                             JSObjectRef thisObject,
670                             JSStringRef propertyName,
671                             JSValueRef *exception)
672 {
673     LdmGreeter *greeter = JSObjectGetPrivate (thisObject);
674     return JSValueMakeString (context, JSStringCreateWithUTF8CString (ldm_greeter_get_authentication_user (greeter)));
675 }
676
677 static JSValueRef
678 get_is_authenticated_cb (JSContextRef context,
679                          JSObjectRef thisObject,
680                          JSStringRef propertyName,
681                          JSValueRef *exception)
682 {
683     LdmGreeter *greeter = JSObjectGetPrivate (thisObject);
684     return JSValueMakeBoolean (context, ldm_greeter_get_is_authenticated (greeter));
685 }
686
687 static JSValueRef
688 get_can_suspend_cb (JSContextRef context,
689                     JSObjectRef thisObject,
690                     JSStringRef propertyName,
691                     JSValueRef *exception)
692 {
693     LdmGreeter *greeter = JSObjectGetPrivate (thisObject);
694     return JSValueMakeBoolean (context, ldm_greeter_get_can_suspend (greeter));
695 }
696
697 static JSValueRef
698 suspend_cb (JSContextRef context,
699             JSObjectRef function,
700             JSObjectRef thisObject,
701             size_t argumentCount,
702             const JSValueRef arguments[],
703             JSValueRef *exception)
704 {
705     LdmGreeter *greeter = JSObjectGetPrivate (thisObject);
706
707     // FIXME: Throw exception
708     if (argumentCount != 0)
709         return JSValueMakeNull (context);
710
711     ldm_greeter_suspend (greeter);
712     return JSValueMakeNull (context);
713 }
714
715 static JSValueRef
716 get_can_hibernate_cb (JSContextRef context,
717                       JSObjectRef thisObject,
718                       JSStringRef propertyName,
719                       JSValueRef *exception)
720 {
721     LdmGreeter *greeter = JSObjectGetPrivate (thisObject);
722     return JSValueMakeBoolean (context, ldm_greeter_get_can_hibernate (greeter));
723 }
724
725 static JSValueRef
726 hibernate_cb (JSContextRef context,
727               JSObjectRef function,
728               JSObjectRef thisObject,
729               size_t argumentCount,
730               const JSValueRef arguments[],
731               JSValueRef *exception)
732 {
733     LdmGreeter *greeter = JSObjectGetPrivate (thisObject);
734
735     // FIXME: Throw exception
736     if (argumentCount != 0)
737         return JSValueMakeNull (context);
738
739     ldm_greeter_hibernate (greeter);
740     return JSValueMakeNull (context);
741 }
742
743 static JSValueRef
744 get_can_restart_cb (JSContextRef context,
745                     JSObjectRef thisObject,
746                     JSStringRef propertyName,
747                     JSValueRef *exception)
748 {
749     LdmGreeter *greeter = JSObjectGetPrivate (thisObject);
750     return JSValueMakeBoolean (context, ldm_greeter_get_can_restart (greeter));
751 }
752
753 static JSValueRef
754 restart_cb (JSContextRef context,
755             JSObjectRef function,
756             JSObjectRef thisObject,
757             size_t argumentCount,
758             const JSValueRef arguments[],
759             JSValueRef *exception)
760 {
761     LdmGreeter *greeter = JSObjectGetPrivate (thisObject);
762
763     // FIXME: Throw exception
764     if (argumentCount != 0)
765         return JSValueMakeNull (context);
766
767     ldm_greeter_restart (greeter);
768     return JSValueMakeNull (context);
769 }
770
771 static JSValueRef
772 get_can_shutdown_cb (JSContextRef context,
773                      JSObjectRef thisObject,
774                      JSStringRef propertyName,
775                      JSValueRef *exception)
776 {
777     LdmGreeter *greeter = JSObjectGetPrivate (thisObject);
778     return JSValueMakeBoolean (context, ldm_greeter_get_can_shutdown (greeter));
779 }
780
781 static JSValueRef
782 shutdown_cb (JSContextRef context,
783              JSObjectRef function,
784              JSObjectRef thisObject,
785              size_t argumentCount,
786              const JSValueRef arguments[],
787              JSValueRef *exception)
788 {
789     LdmGreeter *greeter = JSObjectGetPrivate (thisObject);
790
791     // FIXME: Throw exception
792     if (argumentCount != 0)
793         return JSValueMakeNull (context);
794
795     ldm_greeter_shutdown (greeter);
796     return JSValueMakeNull (context);
797 }
798
799 static JSValueRef
800 login_cb (JSContextRef context,
801           JSObjectRef function,
802           JSObjectRef thisObject,
803           size_t argumentCount,
804           const JSValueRef arguments[],
805           JSValueRef *exception)
806 {
807     LdmGreeter *greeter = JSObjectGetPrivate (thisObject);
808     JSStringRef arg;
809     char username[1024], *session = NULL, *language = NULL;
810
811     // FIXME: Throw exception
812     if (argumentCount < 1 || argumentCount > 3)
813         return JSValueMakeNull (context);
814
815     arg = JSValueToStringCopy (context, arguments[0], NULL);
816     JSStringGetUTF8CString (arg, username, 1024);
817     JSStringRelease (arg);
818
819     if (argumentCount > 1)
820     {
821         arg = JSValueToStringCopy (context, arguments[1], NULL);
822         session = g_malloc (sizeof (char) * 1024);
823         JSStringGetUTF8CString (arg, session, 1024);
824         JSStringRelease (arg);
825     }
826
827     if (argumentCount > 2)
828     {
829         arg = JSValueToStringCopy (context, arguments[1], NULL);
830         language = g_malloc (sizeof (char) * 1024);
831         JSStringGetUTF8CString (arg, language, 1024);
832         JSStringRelease (arg);
833     }
834
835     ldm_greeter_login (greeter, username, session, language);
836     g_free (session);
837     g_free (language);
838
839     return JSValueMakeNull (context);
840 }
841
842 static JSValueRef
843 gettext_cb (JSContextRef context,
844             JSObjectRef function,
845             JSObjectRef thisObject,
846             size_t argumentCount,
847             const JSValueRef arguments[],
848             JSValueRef *exception)
849 {
850     JSStringRef string_arg, result;
851     char string[1024];
852
853     // FIXME: Throw exception
854     if (argumentCount != 1)
855         return JSValueMakeNull (context);
856
857     string_arg = JSValueToStringCopy (context, arguments[0], NULL);
858     JSStringGetUTF8CString (string_arg, string, 1024);
859     JSStringRelease (string_arg);
860
861     result = JSStringCreateWithUTF8CString (gettext (string));
862     return JSValueMakeString (context, result);
863 }
864
865 static JSValueRef
866 ngettext_cb (JSContextRef context,
867              JSObjectRef function,
868              JSObjectRef thisObject,
869              size_t argumentCount,
870              const JSValueRef arguments[],
871              JSValueRef *exception)
872 {
873     JSStringRef string_arg, plural_string_arg, result;
874     char string[1024], plural_string[1024];
875     unsigned int n;
876
877     // FIXME: Throw exception
878     if (argumentCount != 3)
879         return JSValueMakeNull (context);
880
881     string_arg = JSValueToStringCopy (context, arguments[0], NULL);
882     JSStringGetUTF8CString (string_arg, string, 1024);
883     JSStringRelease (string_arg);
884
885     plural_string_arg = JSValueToStringCopy (context, arguments[1], NULL);
886     JSStringGetUTF8CString (plural_string_arg, string, 1024);
887     JSStringRelease (plural_string_arg);
888
889     n = JSValueToNumber (context, arguments[2], NULL);
890
891     result = JSStringCreateWithUTF8CString (ngettext (string, plural_string, n));
892     return JSValueMakeString (context, result);
893 }
894
895 static const JSStaticValue ldm_user_values[] =
896 {
897     { "name", get_user_name_cb, NULL, kJSPropertyAttributeReadOnly },
898     { "real_name", get_user_real_name_cb, NULL, kJSPropertyAttributeReadOnly },
899     { "display_name", get_user_display_name_cb, NULL, kJSPropertyAttributeReadOnly },
900     { "image", get_user_image_cb, NULL, kJSPropertyAttributeReadOnly },
901     { "logged_in", get_user_logged_in_cb, NULL, kJSPropertyAttributeReadOnly },
902     { NULL, NULL, NULL, 0 }
903 };
904
905 static const JSStaticValue ldm_language_values[] =
906 {
907     { "code", get_language_code_cb, NULL, kJSPropertyAttributeReadOnly },
908     { "name", get_language_name_cb, NULL, kJSPropertyAttributeReadOnly },
909     { "territory", get_language_territory_cb, NULL, kJSPropertyAttributeReadOnly },
910     { NULL, NULL, NULL, 0 }
911 };
912
913 static const JSStaticValue ldm_layout_values[] =
914 {
915     { "name", get_layout_name_cb, NULL, kJSPropertyAttributeReadOnly },
916     { "short_description", get_layout_short_description_cb, NULL, kJSPropertyAttributeReadOnly },
917     { "description", get_layout_description_cb, NULL, kJSPropertyAttributeReadOnly },
918     { NULL, NULL, NULL, 0 }
919 };
920
921 static const JSStaticValue ldm_session_values[] =
922 {
923     { "key", get_session_key_cb, NULL, kJSPropertyAttributeReadOnly },
924     { "name", get_session_name_cb, NULL, kJSPropertyAttributeReadOnly },
925     { "comment", get_session_comment_cb, NULL, kJSPropertyAttributeReadOnly },
926     { NULL, NULL, NULL, 0 }
927 };
928
929 static const JSStaticValue ldm_greeter_values[] =
930 {
931     { "hostname", get_hostname_cb, NULL, kJSPropertyAttributeReadOnly },
932     { "users", get_users_cb, NULL, kJSPropertyAttributeReadOnly },
933     { "default_language", get_default_language_cb, NULL, kJSPropertyAttributeReadOnly },
934     { "languages", get_languages_cb, NULL, kJSPropertyAttributeReadOnly },
935     { "default_layout", get_default_layout_cb, NULL, kJSPropertyAttributeReadOnly },
936     { "layouts", get_layouts_cb, NULL, kJSPropertyAttributeReadOnly },
937     { "layout", get_layout_cb, set_layout_cb, kJSPropertyAttributeReadOnly },
938     { "sessions", get_sessions_cb, NULL, kJSPropertyAttributeReadOnly },
939     { "num_users", get_num_users_cb, NULL, kJSPropertyAttributeReadOnly },
940     { "default_session", get_default_session_cb, NULL, kJSPropertyAttributeNone },
941     { "timed_login_user", get_timed_login_user_cb, NULL, kJSPropertyAttributeReadOnly },
942     { "timed_login_delay", get_timed_login_delay_cb, NULL, kJSPropertyAttributeReadOnly },
943     { "authentication_user", get_authentication_user_cb, NULL, kJSPropertyAttributeReadOnly },
944     { "is_authenticated", get_is_authenticated_cb, NULL, kJSPropertyAttributeReadOnly },
945     { "can_suspend", get_can_suspend_cb, NULL, kJSPropertyAttributeReadOnly },
946     { "can_hibernate", get_can_hibernate_cb, NULL, kJSPropertyAttributeReadOnly },
947     { "can_restart", get_can_restart_cb, NULL, kJSPropertyAttributeReadOnly },
948     { "can_shutdown", get_can_shutdown_cb, NULL, kJSPropertyAttributeReadOnly },
949     { NULL, NULL, NULL, 0 }
950 };
951
952 static const JSStaticFunction ldm_greeter_functions[] =
953 {
954     { "get_string_property", get_string_property_cb, kJSPropertyAttributeReadOnly },
955     { "get_integer_property", get_integer_property_cb, kJSPropertyAttributeReadOnly },
956     { "get_boolean_property", get_boolean_property_cb, kJSPropertyAttributeReadOnly },
957     { "cancel_timed_login", cancel_timed_login_cb, kJSPropertyAttributeReadOnly },
958     { "start_authentication", start_authentication_cb, kJSPropertyAttributeReadOnly },
959     { "provide_secret", provide_secret_cb, kJSPropertyAttributeReadOnly },
960     { "cancel_authentication", cancel_authentication_cb, kJSPropertyAttributeReadOnly },
961     { "suspend", suspend_cb, kJSPropertyAttributeReadOnly },
962     { "hibernate", hibernate_cb, kJSPropertyAttributeReadOnly },
963     { "restart", restart_cb, kJSPropertyAttributeReadOnly },
964     { "shutdown", shutdown_cb, kJSPropertyAttributeReadOnly },
965     { "login", login_cb, kJSPropertyAttributeReadOnly },
966     { NULL, NULL, 0 }
967 };
968
969 static const JSStaticFunction gettext_functions[] =
970 {
971     { "gettext", gettext_cb, kJSPropertyAttributeReadOnly },
972     { "ngettext", ngettext_cb, kJSPropertyAttributeReadOnly },
973     { NULL, NULL, 0 }
974 };
975
976 static const JSClassDefinition ldm_user_definition =
977 {
978     0,                     /* Version */
979     kJSClassAttributeNone, /* Attributes */
980     "LdmUser",             /* Class name */
981     NULL,                  /* Parent class */
982     ldm_user_values,       /* Static values */
983 };
984
985 static const JSClassDefinition ldm_language_definition =
986 {
987     0,                     /* Version */
988     kJSClassAttributeNone, /* Attributes */
989     "LdmLanguage",         /* Class name */
990     NULL,                  /* Parent class */
991     ldm_language_values,   /* Static values */
992 };
993
994 static const JSClassDefinition ldm_layout_definition =
995 {
996     0,                     /* Version */
997     kJSClassAttributeNone, /* Attributes */
998     "LdmLayout",           /* Class name */
999     NULL,                  /* Parent class */
1000     ldm_layout_values,     /* Static values */
1001 };
1002
1003 static const JSClassDefinition ldm_session_definition =
1004 {
1005     0,                     /* Version */
1006     kJSClassAttributeNone, /* Attributes */
1007     "LdmSession",          /* Class name */
1008     NULL,                  /* Parent class */
1009     ldm_session_values,    /* Static values */
1010 };
1011
1012 static const JSClassDefinition ldm_greeter_definition =
1013 {
1014     0,                     /* Version */
1015     kJSClassAttributeNone, /* Attributes */
1016     "LdmGreeter",          /* Class name */
1017     NULL,                  /* Parent class */
1018     ldm_greeter_values,    /* Static values */
1019     ldm_greeter_functions, /* Static functions */
1020 };
1021
1022 static const JSClassDefinition gettext_definition =
1023 {
1024     0,                     /* Version */
1025     kJSClassAttributeNone, /* Attributes */
1026     "GettextClass",        /* Class name */
1027     NULL,                  /* Parent class */
1028     NULL,
1029     gettext_functions,     /* Static functions */
1030 };
1031
1032 static void
1033 window_object_cleared_cb (WebKitWebView  *web_view,
1034                           WebKitWebFrame *frame,
1035                           JSGlobalContextRef context,
1036                           JSObjectRef window_object,
1037                           LdmGreeter *greeter)
1038 {
1039     JSObjectRef gettext_object, ldm_greeter_object;
1040
1041     gettext_class = JSClassCreate (&gettext_definition);
1042     ldm_greeter_class = JSClassCreate (&ldm_greeter_definition);
1043     ldm_user_class = JSClassCreate (&ldm_user_definition);
1044     ldm_language_class = JSClassCreate (&ldm_language_definition);
1045     ldm_layout_class = JSClassCreate (&ldm_layout_definition);
1046     ldm_session_class = JSClassCreate (&ldm_session_definition);
1047
1048     gettext_object = JSObjectMake (context, gettext_class, NULL);
1049     JSObjectSetProperty (context,
1050                          JSContextGetGlobalObject (context),
1051                          JSStringCreateWithUTF8CString ("gettext"),
1052                          gettext_object, kJSPropertyAttributeNone, NULL);
1053
1054     ldm_greeter_object = JSObjectMake (context, ldm_greeter_class, greeter);
1055     JSObjectSetProperty (context,
1056                          JSContextGetGlobalObject (context),
1057                          JSStringCreateWithUTF8CString ("lightdm"),
1058                          ldm_greeter_object, kJSPropertyAttributeNone, NULL);
1059 }
1060
1061 static void
1062 sigterm_cb (int signum)
1063 {
1064     exit (0);
1065 }
1066
1067 int
1068 main(int argc, char **argv)
1069 {
1070     LdmGreeter *greeter;
1071     GdkDisplay *display;
1072     GdkScreen *screen;
1073     gint screen_width, screen_height;
1074     GtkWidget *web_view;
1075     gchar *url;
1076
1077     signal (SIGTERM, sigterm_cb);
1078
1079     gtk_init (&argc, &argv);
1080
1081     if (argc != 2) {
1082         g_printerr ("Usage: %s <url>\n", argv[0]);
1083         return 1;
1084     }
1085     url = argv[1];
1086
1087     greeter = ldm_greeter_new ();
1088
1089     display = gdk_display_get_default ();
1090     screen = gdk_display_get_default_screen (display);
1091     screen_width = gdk_screen_get_width (screen);
1092     screen_height = gdk_screen_get_height (screen);
1093
1094     window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
1095     gtk_window_set_default_size (GTK_WINDOW (window), screen_width, screen_height);
1096     gtk_window_fullscreen (GTK_WINDOW (window));
1097
1098     web_view = webkit_web_view_new ();
1099     g_signal_connect (G_OBJECT (web_view), "window-object-cleared", G_CALLBACK (window_object_cleared_cb), greeter);
1100     gtk_container_add (GTK_CONTAINER (window), web_view);
1101
1102     g_signal_connect (G_OBJECT (greeter), "show-prompt", G_CALLBACK (show_prompt_cb), web_view);
1103     g_signal_connect (G_OBJECT (greeter), "show-message", G_CALLBACK (show_message_cb), web_view);
1104     g_signal_connect (G_OBJECT (greeter), "show-error", G_CALLBACK (show_message_cb), web_view);
1105     g_signal_connect (G_OBJECT (greeter), "authentication-complete", G_CALLBACK (authentication_complete_cb), web_view);
1106     g_signal_connect (G_OBJECT (greeter), "timed-login", G_CALLBACK (timed_login_cb), web_view);
1107     g_signal_connect (G_OBJECT (greeter), "quit", G_CALLBACK (quit_cb), web_view);
1108
1109     webkit_web_view_load_uri (WEBKIT_WEB_VIEW (web_view), url);
1110     ldm_greeter_connect (greeter);
1111
1112     gtk_widget_show_all (window);
1113
1114     gtk_main ();
1115
1116     return 0;
1117 }