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