Merge "[WK2] Small Caps font variant issue for Italic fonts" into tizen_2.2
[framework/web/webkit-efl.git] / Tools / EWebLauncher / main.c
1 /*
2  * Copyright (C) 2008 INdT - Instituto Nokia de Tecnologia
3  * Copyright (C) 2009, 2010 ProFUSION embedded systems
4  * Copyright (C) 2009, 2010, 2011 Samsung Electronics
5  * Copyright (C) 2012 Intel Corporation
6  *
7  * All rights reserved.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer.
14  * 2. Redistributions in binary form must reproduce the above copyright
15  *    notice, this list of conditions and the following disclaimer in the
16  *    documentation and/or other materials provided with the distribution.
17  *
18  * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
19  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
21  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
22  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
23  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
24  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
25  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
26  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29  */
30
31 #include "EWebKit.h"
32
33 #include "url_bar.h"
34 #include "url_utils.h"
35 #include <Ecore.h>
36 #include <Ecore_Evas.h>
37 #include <Ecore_File.h>
38 #include <Ecore_Getopt.h>
39 #include <Ecore_X.h>
40 #include <Edje.h>
41 #include <Evas.h>
42 #include <ctype.h>
43 #include <inttypes.h>
44 #include <limits.h>
45 #include <stdio.h>
46 #include <stdlib.h>
47 #include <string.h>
48 #include <sys/stat.h>
49 #include <sys/types.h>
50 #include <unistd.h>
51
52 #define DEFAULT_WIDTH      800
53 #define DEFAULT_HEIGHT     600
54 #define DEFAULT_ZOOM_INIT  1.0
55
56 #define info(format, args...)       \
57     do {                            \
58         if (verbose)                \
59             printf(format, ##args); \
60     } while (0)
61
62 #define MIN_ZOOM_LEVEL 0
63 #define DEFAULT_ZOOM_LEVEL 5
64 #define MAX_ZOOM_LEVEL 13
65
66 static int currentZoomLevel = DEFAULT_ZOOM_LEVEL;
67 static float currentZoom = 1.0;
68
69 // the zoom values are chosen to be like in Mozilla Firefox 3
70 static int zoomLevels[] = {30, 50, 67, 80, 90,
71                             100,
72                             110, 120, 133, 150, 170, 200, 240, 300};
73
74 static int verbose = 0;
75
76 static Eina_List *windows = NULL;
77
78 static char *themePath = NULL;
79
80 static const char *backingStores[] = {
81     "tiled",
82     "single",
83     NULL
84 };
85
86 typedef struct _Window_Properties {
87     Eina_Bool toolbarsVisible:1;
88     Eina_Bool statusbarVisible:1;
89     Eina_Bool scrollbarsVisible:1;
90     Eina_Bool menubarVisible:1;
91 } Window_Properties;
92
93 Window_Properties windowProperties = { /* Pretend we have them and they are initially visible */
94     EINA_TRUE,
95     EINA_TRUE,
96     EINA_TRUE,
97     EINA_TRUE
98 };
99
100 static const Ecore_Getopt options = {
101     "EWebLauncher",
102     "%prog [options] [url]",
103     "0.0.1",
104     "(C)2008 INdT (The Nokia Technology Institute)\n"
105     "(C)2009, 2010 ProFUSION embedded systems\n"
106     "(C)2009, 2010, 2011 Samsung Electronics\n"
107     "(C)2012 Intel Corporation\n",
108     "GPL",
109     "Test Web Browser using the Enlightenment Foundation Libraries of WebKit",
110     EINA_TRUE, {
111         ECORE_GETOPT_STORE_STR
112             ('e', "engine", "ecore-evas engine to use."),
113         ECORE_GETOPT_CALLBACK_NOARGS
114             ('E', "list-engines", "list ecore-evas engines.",
115              ecore_getopt_callback_ecore_evas_list_engines, NULL),
116         ECORE_GETOPT_CHOICE
117             ('b', "backing-store", "choose backing store to use.", backingStores),
118         ECORE_GETOPT_STORE_DEF_BOOL
119             ('f', "flattening", "frame flattening.", 0),
120         ECORE_GETOPT_STORE_DEF_BOOL
121             ('F', "fullscreen", "fullscreen mode.", 0),
122         ECORE_GETOPT_CALLBACK_ARGS
123             ('g', "geometry", "geometry to use in x:y:w:h form.", "X:Y:W:H",
124              ecore_getopt_callback_geometry_parse, NULL),
125         ECORE_GETOPT_STORE_STR
126             ('t', "theme", "path to read the theme file from."),
127         ECORE_GETOPT_STORE_STR
128             ('U', "user-agent", "custom user agent string to use."),
129         ECORE_GETOPT_COUNT
130             ('v', "verbose", "be more verbose."),
131         ECORE_GETOPT_VERSION
132             ('V', "version"),
133         ECORE_GETOPT_COPYRIGHT
134             ('R', "copyright"),
135         ECORE_GETOPT_LICENSE
136             ('L', "license"),
137         ECORE_GETOPT_HELP
138             ('h', "help"),
139         ECORE_GETOPT_SENTINEL
140     }
141 };
142
143 typedef struct _ELauncher {
144     Ecore_Evas *ee;
145     Evas *evas;
146     Evas_Object *bg;
147     Evas_Object *browser;
148     Url_Bar *url_bar;
149     const char *theme;
150     const char *userAgent;
151     const char *backingStore;
152     unsigned char isFlattening;
153 } ELauncher;
154
155 static void browserDestroy(Ecore_Evas *ee);
156 static void closeWindow(Ecore_Evas *ee);
157 static int browserCreate(const char *url, const char *theme, const char *userAgent, Eina_Rectangle geometry, const char *engine, const char *backingStore, unsigned char isFlattening, unsigned char isFullscreen, const char *databasePath);
158
159 static ELauncher *
160 find_app_from_ee(Ecore_Evas *ee)
161 {
162     Eina_List *l;
163     void *data;
164
165     EINA_LIST_FOREACH(windows, l, data)
166     {
167         ELauncher *app = (ELauncher *) data;
168         if (app->ee == ee)
169             return app;
170     }
171     return NULL;
172 }
173
174 static void
175 print_history(Eina_List *list)
176 {
177     Eina_List *l;
178     void *d;
179
180     if (!verbose)
181        return;
182
183     printf("Session history contains:\n");
184
185     EINA_LIST_FOREACH(list, l, d) {
186        Ewk_History_Item *item = (Ewk_History_Item*)d;
187        cairo_surface_t *cs = ewk_history_item_icon_surface_get(item);
188        char buf[PATH_MAX];
189        int s = snprintf(buf, sizeof(buf), "/tmp/favicon-%s.png", ewk_history_item_uri_original_get(item));
190        for (s--; s >= (int)sizeof("/tmp/favicon-"); s--) {
191            if (!isalnum(buf[s]) && buf[s] != '.')
192                buf[s] = '_';
193        }
194        cs = ewk_history_item_icon_surface_get(item);
195
196        if (cs && cairo_surface_status(cs) == CAIRO_STATUS_SUCCESS)
197            cairo_surface_write_to_png(cs, buf);
198        else
199            buf[0] = '\0';
200
201        printf("* '%s' title='%s' icon='%s'\n",
202               ewk_history_item_uri_original_get(item),
203               ewk_history_item_title_get(item), buf);
204     }
205 }
206
207 static int
208 nearest_zoom_level_get(float factor)
209 {
210     int i, intFactor = (int)(factor * 100.0);
211     for (i = 0; zoomLevels[i] <= intFactor; i++) { }
212     printf("factor=%f, intFactor=%d, zoomLevels[%d]=%d, zoomLevels[%d]=%d\n",
213            factor, intFactor, i-1, zoomLevels[i-1], i, zoomLevels[i]);
214     if (intFactor - zoomLevels[i-1] < zoomLevels[i] - intFactor)
215         return i - 1;
216     return i;
217 }
218
219 static Eina_Bool
220 zoom_level_set(Evas_Object *webview, int level)
221 {
222     float factor = ((float) zoomLevels[level]) / 100.0;
223     Evas_Coord ox, oy, mx, my, cx, cy;
224     evas_pointer_canvas_xy_get(evas_object_evas_get(webview), &mx, &my);
225     evas_object_geometry_get(webview, &ox, &oy, NULL, NULL);
226     cx = mx - ox;
227     cy = my - oy;
228     return ewk_view_zoom_animated_set(webview, factor, 0.5, cx, cy);
229 }
230
231 static void
232 on_ecore_evas_resize(Ecore_Evas *ee)
233 {
234     ELauncher *app;
235     Evas_Object *webview;
236     Evas_Object *bg;
237     int w, h;
238
239     ecore_evas_geometry_get(ee, NULL, NULL, &w, &h);
240
241     /* Resize URL bar */
242     app = find_app_from_ee(ee);
243     url_bar_width_set(app->url_bar, w);
244
245     bg = evas_object_name_find(ecore_evas_get(ee), "bg");
246     evas_object_move(bg, 0, 0);
247     evas_object_resize(bg, w, h);
248
249     webview = evas_object_name_find(ecore_evas_get(ee), "browser");
250     evas_object_move(webview, 0, URL_BAR_HEIGHT);
251     evas_object_resize(webview, w, h - URL_BAR_HEIGHT);
252 }
253
254 static void
255 title_set(Ecore_Evas *ee, const Ewk_Text_With_Direction *title, int progress)
256 {
257     const char *appname = "EFL Test Launcher";
258     const char *separator = " - ";
259     char label[4096];
260     int size;
261
262     if (!title || !title->string || !strcmp(title->string, "")) {
263         ecore_evas_title_set(ee, appname);
264         return;
265     }
266
267     if (progress < 100)
268         size = snprintf(label, sizeof(label), "%s (%d%%)%s%s", title->string, progress, separator, appname);
269     else
270         size = snprintf(label, sizeof(label), "%s %s%s", title->string, separator, appname);
271
272     if (size >= (int)sizeof(label))
273         return;
274
275     ecore_evas_title_set(ee, label);
276 }
277
278 static void
279 on_title_changed(void *user_data, Evas_Object *webview, void *event_info)
280 {
281     ELauncher *app = (ELauncher *)user_data;
282     const Ewk_Text_With_Direction *title = (const Ewk_Text_With_Direction *)event_info;
283
284     title_set(app->ee, title, 100);
285 }
286
287 static void
288 on_progress(void *user_data, Evas_Object *webview, void *event_info)
289 {
290     ELauncher *app = (ELauncher *)user_data;
291     double *progress = (double *)event_info;
292
293     title_set(app->ee, ewk_view_title_get(app->browser), *progress * 100);
294 }
295
296 static void
297 on_load_finished(void *user_data, Evas_Object *webview, void *event_info)
298 {
299     const Ewk_Frame_Load_Error *err = (const Ewk_Frame_Load_Error *)event_info;
300
301     if (!err)
302         info("Succeeded loading page.\n");
303     else if (err->is_cancellation)
304         info("Load was cancelled.\n");
305     else
306         info("Failed loading page: %d %s \"%s\", url=%s\n",
307              err->code, err->domain, err->description, err->failing_url);
308
309     currentZoom = ewk_view_zoom_get(webview);
310     currentZoomLevel = nearest_zoom_level_get(currentZoom);
311     info("WebCore Zoom=%f, currentZoomLevel=%d\n", currentZoom, currentZoomLevel);
312 }
313
314 static void
315 on_load_error(void *user_data, Evas_Object *webview, void *event_info)
316 {
317     const Ewk_Frame_Load_Error *err = (const Ewk_Frame_Load_Error *)event_info;
318     char message[1024];
319     snprintf(message, 1024, "<html><body><div style=\"color:#ff0000\">ERROR!</div><br><div>Code: %d<br>Domain: %s<br>Description: %s<br>URL: %s</div></body</html>",
320              err->code, err->domain, err->description, err->failing_url);
321     ewk_frame_contents_set(err->frame, message, 0, "text/html", "UTF-8", err->failing_url);
322 }
323
324 static void
325 on_toolbars_visible_set(void* user_data, Evas_Object* webview, void* event_info)
326 {
327     Eina_Bool *visible = (Eina_Bool *)event_info;
328     if (*visible) {
329         info("Toolbars visible changed: show");
330         windowProperties.toolbarsVisible = EINA_TRUE;
331     } else {
332         info("Toolbars visible changed: hide");
333         windowProperties.toolbarsVisible = EINA_FALSE;
334     }
335 }
336
337 static void
338 on_toolbars_visible_get(void* user_data, Evas_Object* webview, void* event_info)
339 {
340     Eina_Bool *visible = (Eina_Bool *)event_info;
341     *visible = windowProperties.toolbarsVisible;
342 }
343
344 static void
345 on_statusbar_visible_set(void* user_data, Evas_Object* webview, void* event_info)
346 {
347     Eina_Bool *visible = (Eina_Bool *)event_info;
348     if (*visible) {
349         info("Statusbar visible changed: show");
350         windowProperties.statusbarVisible = EINA_TRUE;
351     } else {
352         info("Statusbar visible changed: hide");
353         windowProperties.statusbarVisible = EINA_FALSE;
354     }
355 }
356
357 static void
358 on_statusbar_visible_get(void* user_data, Evas_Object* webview, void* event_info)
359 {
360     Eina_Bool *visible = (Eina_Bool *)event_info;
361     *visible = windowProperties.statusbarVisible;
362 }
363
364 static void
365 on_scrollbars_visible_set(void* user_data, Evas_Object* webview, void* event_info)
366 {
367     Eina_Bool *visible = (Eina_Bool *)event_info;
368     if (*visible) {
369         info("Scrollbars visible changed: show");
370         windowProperties.scrollbarsVisible = EINA_TRUE;
371     } else {
372         info("Scrollbars visible changed: hide");
373         windowProperties.scrollbarsVisible = EINA_FALSE;
374     }
375 }
376
377 static void
378 on_scrollbars_visible_get(void* user_data, Evas_Object* webview, void* event_info)
379 {
380     Eina_Bool *visible = (Eina_Bool *)event_info;
381     *visible = windowProperties.scrollbarsVisible;
382 }
383
384 static void
385 on_menubar_visible_set(void* user_data, Evas_Object* webview, void* event_info)
386 {
387     Eina_Bool *visible = (Eina_Bool *)event_info;
388     if (*visible) {
389         info("Menubar visible changed: show");
390         windowProperties.menubarVisible = EINA_TRUE;
391     } else {
392         info("Menubar visible changed: hide");
393         windowProperties.menubarVisible = EINA_FALSE;
394     }
395 }
396
397 static void
398 on_menubar_visible_get(void* user_data, Evas_Object* webview, void* event_info)
399 {
400     Eina_Bool *visible = (Eina_Bool *)event_info;
401     *visible = windowProperties.menubarVisible;
402 }
403
404 static void
405 on_tooltip_text_set(void* user_data, Evas_Object* webview, void* event_info)
406 {
407     const char *text = (const char *)event_info;
408     if (text && *text != '\0')
409         info("%s\n", text);
410 }
411
412 static void
413 on_inputmethod_changed(void* user_data, Evas_Object* webview, void* event_info)
414 {
415     Eina_Bool active = (Eina_Bool)(long)event_info;
416     unsigned int imh;
417     info("Keyboard changed: %d\n", active);
418
419     if (!active)
420         return;
421
422     imh = ewk_view_imh_get(webview);
423     info("    Keyboard flags: %#.2x\n", imh);
424
425 }
426
427 static void
428 on_url_changed(void* user_data, Evas_Object* webview, void* event_info)
429 {
430     ELauncher *app = (ELauncher *)user_data;
431     url_bar_url_set(app->url_bar, ewk_view_uri_get(app->browser));
432 }
433
434 static void
435 on_mouse_down(void* data, Evas* e, Evas_Object* webview, void* event_info)
436 {
437     Evas_Event_Mouse_Down *ev = (Evas_Event_Mouse_Down*) event_info;
438     if (ev->button == 2)
439         evas_object_focus_set(webview, !evas_object_focus_get(webview));
440 }
441
442 static void
443 on_focus_out(void *data, Evas *e, Evas_Object *obj, void *event_info)
444 {
445     info("the webview lost keyboard focus\n");
446 }
447
448 static void
449 on_focus_in(void *data, Evas *e, Evas_Object *obj, void *event_info)
450 {
451     info("the webview gained keyboard focus\n");
452 }
453
454 static void
455 on_key_down(void *data, Evas *e, Evas_Object *obj, void *event_info)
456 {
457     Evas_Event_Key_Down *ev = (Evas_Event_Key_Down*) event_info;
458     ELauncher *app = data;
459     static const char *encodings[] = {
460         "ISO-8859-1",
461         "UTF-8",
462         NULL
463     };
464     static int currentEncoding = -1;
465     Eina_Bool ctrlPressed = evas_key_modifier_is_set(evas_key_modifier_get(e), "Control");
466
467     if (!strcmp(ev->key, "Escape")) {
468         closeWindow(app->ee);
469     } else if (!strcmp(ev->key, "F1")) {
470         info("Back (F1) was pressed\n");
471         if (ewk_view_back_possible(obj)) {
472             Ewk_History *history = ewk_view_history_get(obj);
473             Eina_List *list = ewk_history_back_list_get(history);
474             print_history(list);
475             ewk_history_item_list_free(list);
476             ewk_view_back(obj);
477         } else
478             info("Back ignored: No back history\n");
479     } else if (!strcmp(ev->key, "F2")) {
480         info("Forward (F2) was pressed\n");
481         if (ewk_view_forward_possible(obj)) {
482             Ewk_History *history = ewk_view_history_get(obj);
483             Eina_List *list = ewk_history_forward_list_get(history);
484             print_history(list);
485             ewk_history_item_list_free(list);
486             ewk_view_forward(obj);
487         } else
488             info("Forward ignored: No forward history\n");
489     } else if (!strcmp(ev->key, "F3")) {
490         currentEncoding++;
491         currentEncoding %= (sizeof(encodings) / sizeof(encodings[0]));
492         info("Set encoding (F3) pressed. New encoding to %s", encodings[currentEncoding]);
493         ewk_view_setting_encoding_custom_set(obj, encodings[currentEncoding]);
494     } else if (!strcmp(ev->key, "F4")) {
495         Evas_Object *frame = ewk_view_frame_main_get(obj);
496         Evas_Coord x, y;
497         Ewk_Hit_Test *ht;
498
499         evas_pointer_canvas_xy_get(evas_object_evas_get(obj), &x, &y);
500         ht = ewk_frame_hit_test_new(frame, x, y);
501         if (!ht)
502             printf("No hit test returned for point %d,%d\n", x, y);
503         else {
504             printf("Hit test for point %d,%d\n"
505                    "  pos=%3d,%3d\n"
506                    "  bounding_box=%d,%d + %dx%d\n"
507                    "  title='%s'\n"
508                    "  alternate_text='%s'\n"
509                    "  frame=%p (%s)\n"
510                    "  link {\n"
511                    "    text='%s'\n"
512                    "    url='%s'\n"
513                    "    title='%s'\n"
514                    "    target frame=%p (%s)\n"
515                    "  }\n"
516                    "context:\n"
517                    "%s"
518                    "%s"
519                    "%s"
520                    "%s"
521                    "%s\n",
522                    x, y,
523                    ht->x, ht->y,
524                    ht->bounding_box.x, ht->bounding_box.y, ht->bounding_box.w, ht->bounding_box.h,
525                    ht->title.string,
526                    ht->alternate_text,
527                    ht->frame, evas_object_name_get(ht->frame),
528                    ht->link.text,
529                    ht->link.url,
530                    ht->link.title,
531                    ht->link.target_frame, evas_object_name_get(ht->link.target_frame),
532                    ht->context & EWK_HIT_TEST_RESULT_CONTEXT_LINK ? "  LINK\n" : "",
533                    ht->context & EWK_HIT_TEST_RESULT_CONTEXT_IMAGE ? "  IMAGE\n" : "",
534                    ht->context & EWK_HIT_TEST_RESULT_CONTEXT_MEDIA ? "   MEDIA\n" : "",
535                    ht->context & EWK_HIT_TEST_RESULT_CONTEXT_SELECTION ? "  SELECTION\n" : "",
536                    ht->context & EWK_HIT_TEST_RESULT_CONTEXT_EDITABLE ? "  EDITABLE" : "");
537             ewk_frame_hit_test_free(ht);
538         }
539
540     } else if (!strcmp(ev->key, "F5")) {
541         info("Reload (F5) was pressed, reloading.\n");
542         ewk_view_reload(obj);
543     } else if (!strcmp(ev->key, "F6")) {
544         info("Stop (F6) was pressed, stop loading.\n");
545         ewk_view_stop(obj);
546     } else if (!strcmp(ev->key, "F12")) {
547         Eina_Bool status = ewk_view_setting_spatial_navigation_get(obj);
548         ewk_view_setting_spatial_navigation_set(obj, !status);
549         info("Command::keyboard navigation toggle\n");
550     } else if (!strcmp(ev->key, "F7")) {
551         info("Zoom out (F7) was pressed.\n");
552         if (currentZoomLevel > MIN_ZOOM_LEVEL && zoom_level_set(obj, currentZoomLevel - 1))
553             currentZoomLevel--;
554     } else if (!strcmp(ev->key, "F8")) {
555         info("Zoom in (F8) was pressed.\n");
556         if (currentZoomLevel < MAX_ZOOM_LEVEL && zoom_level_set(obj, currentZoomLevel + 1))
557             currentZoomLevel++;
558     } else if (!strcmp(ev->key, "F9")) {
559         info("Create new window (F9) was pressed.\n");
560         Eina_Rectangle geometry = {0, 0, 0, 0};
561         browserCreate("http://www.google.com",
562                        app->theme, app->userAgent, geometry, NULL,
563                        app->backingStore, app->isFlattening, 0, NULL);
564     } else if (!strcmp(ev->key, "g") && ctrlPressed ) {
565         Evas_Coord x, y, w, h;
566         Evas_Object *frame = ewk_view_frame_main_get(obj);
567         float zoom = zoomLevels[currentZoomLevel] / 100.0;
568
569         ewk_frame_visible_content_geometry_get(frame, EINA_FALSE, &x, &y, &w, &h);
570         x -= w;
571         y -= h;
572         w *= 4;
573         h *= 4;
574         info("Pre-render %d,%d + %dx%d\n", x, y, w, h);
575         ewk_view_pre_render_region(obj, x, y, w, h, zoom);
576     } else if (!strcmp(ev->key, "r") && ctrlPressed) {
577         info("Pre-render 1 extra column/row with current zoom");
578         ewk_view_pre_render_relative_radius(obj, 1);
579     } else if (!strcmp(ev->key, "p") && ctrlPressed) {
580         info("Pre-rendering start");
581         ewk_view_pre_render_start(obj);
582     } else if (!strcmp(ev->key, "d") && ctrlPressed) {
583         info("Render suspended");
584         ewk_view_disable_render(obj);
585     } else if (!strcmp(ev->key, "e") && ctrlPressed) {
586         info("Render resumed");
587         ewk_view_enable_render(obj);
588     } else if (!strcmp(ev->key, "s") && ctrlPressed) {
589         Evas_Object *frame = ewk_view_frame_main_get(obj);
590         Ewk_Security_Origin *origin = ewk_frame_security_origin_get(frame);
591         printf("Security origin information:\n"
592                "  protocol=%s\n"
593                "  host=%s\n"
594                "  port=%d\n"
595                "  web database quota=%" PRIu64 "\n",
596                ewk_security_origin_protocol_get(origin),
597                ewk_security_origin_host_get(origin),
598                ewk_security_origin_port_get(origin),
599                ewk_security_origin_web_database_quota_get(origin));
600
601         Eina_List *databaseList = ewk_security_origin_web_database_get_all(origin);
602         Eina_List *listIterator = 0;
603         Ewk_Web_Database *database;
604         EINA_LIST_FOREACH(databaseList, listIterator, database)
605             printf("Database information:\n"
606                    "  name=%s\n"
607                    "  display name=%s\n"
608                    "  filename=%s\n"
609                    "  expected size=%" PRIu64 "\n"
610                    "  size=%" PRIu64 "\n",
611                    ewk_web_database_name_get(database),
612                    ewk_web_database_display_name_get(database),
613                    ewk_web_database_filename_get(database),
614                    ewk_web_database_expected_size_get(database),
615                    ewk_web_database_size_get(database));
616
617         ewk_security_origin_free(origin);
618         ewk_web_database_list_free(databaseList);
619     }
620 }
621
622 static void
623 on_browser_del(void *data, Evas *evas, Evas_Object *browser, void *event)
624 {
625     ELauncher *app = (ELauncher*) data;
626
627     evas_object_event_callback_del(app->browser, EVAS_CALLBACK_KEY_DOWN, on_key_down);
628     evas_object_event_callback_del(app->browser, EVAS_CALLBACK_MOUSE_DOWN, on_mouse_down);
629     evas_object_event_callback_del(app->browser, EVAS_CALLBACK_FOCUS_IN, on_focus_in);
630     evas_object_event_callback_del(app->browser, EVAS_CALLBACK_FOCUS_OUT, on_focus_out);
631     evas_object_event_callback_del(app->browser, EVAS_CALLBACK_DEL, on_browser_del);
632 }
633
634 static int
635 quit(Eina_Bool success, const char *msg)
636 {
637     edje_shutdown();
638     ecore_evas_shutdown();
639     ecore_file_shutdown();
640
641     if (msg)
642         fputs(msg, (success) ? stdout : stderr);
643
644     if (themePath) {
645         free(themePath);
646         themePath = NULL;
647     }
648
649     if (!success)
650         return EXIT_FAILURE;
651
652     return EXIT_SUCCESS;
653 }
654
655 static int
656 browserCreate(const char *url, const char *theme, const char *userAgent, Eina_Rectangle geometry, const char *engine, const char *backingStore, unsigned char isFlattening, unsigned char isFullscreen, const char *databasePath)
657 {
658     if ((geometry.w <= 0) && (geometry.h <= 0)) {
659         geometry.w = DEFAULT_WIDTH;
660         geometry.h = DEFAULT_HEIGHT;
661     }
662
663     ELauncher *app = (ELauncher*) malloc(sizeof(ELauncher));
664     if (!app)
665         return quit(EINA_FALSE, "ERROR: could not create EWebLauncher window\n");
666
667     app->ee = ecore_evas_new(engine, 0, 0, geometry.w, geometry.h, NULL);
668
669     if (!app->ee)
670         return quit(EINA_FALSE, "ERROR: could not construct evas-ecore\n");
671
672     if (isFullscreen)
673         ecore_evas_fullscreen_set(app->ee, EINA_TRUE);
674
675     ecore_evas_title_set(app->ee, "EFL Test Launcher");
676     ecore_evas_callback_resize_set(app->ee, on_ecore_evas_resize);
677     ecore_evas_callback_delete_request_set(app->ee, closeWindow);
678
679     app->evas = ecore_evas_get(app->ee);
680
681     if (!app->evas)
682         return quit(EINA_FALSE, "ERROR: could not get evas from evas-ecore\n");
683
684     app->theme = theme;
685     app->userAgent = userAgent;
686     app->backingStore = backingStore;
687     app->isFlattening = isFlattening;
688
689     app->bg = evas_object_rectangle_add(app->evas);
690     evas_object_name_set(app->bg, "bg");
691     evas_object_color_set(app->bg, 255, 0, 255, 255);
692     evas_object_move(app->bg, 0, 0);
693     evas_object_resize(app->bg, geometry.w, geometry.h);
694     evas_object_layer_set(app->bg, EVAS_LAYER_MIN);
695     evas_object_show(app->bg);
696
697     if (backingStore && !strcasecmp(backingStore, "tiled")) {
698         app->browser = ewk_view_tiled_add(app->evas);
699         info("backing store: tiled\n");
700     } else {
701         app->browser = ewk_view_single_add(app->evas);
702         info("backing store: single\n");
703     }
704
705     ewk_view_theme_set(app->browser, theme);
706     if (userAgent)
707         ewk_view_setting_user_agent_set(app->browser, userAgent);
708     ewk_view_setting_local_storage_database_path_set(app->browser, databasePath);
709     ewk_view_setting_enable_frame_flattening_set(app->browser, isFlattening);
710     
711     evas_object_name_set(app->browser, "browser");
712
713     evas_object_smart_callback_add(app->browser, "title,changed", on_title_changed, app);
714     evas_object_smart_callback_add(app->browser, "load,progress", on_progress, app);
715     evas_object_smart_callback_add(app->browser, "load,finished", on_load_finished, app);
716     evas_object_smart_callback_add(app->browser, "load,error", on_load_error, app);
717
718     evas_object_smart_callback_add(app->browser, "toolbars,visible,set", on_toolbars_visible_set, app);
719     evas_object_smart_callback_add(app->browser, "toolbars,visible,get", on_toolbars_visible_get, app);
720     evas_object_smart_callback_add(app->browser, "statusbar,visible,set", on_statusbar_visible_set, app);
721     evas_object_smart_callback_add(app->browser, "statusbar,visible,get", on_statusbar_visible_get, app);
722     evas_object_smart_callback_add(app->browser, "scrollbars,visible,set", on_scrollbars_visible_set, app);
723     evas_object_smart_callback_add(app->browser, "scrollbars,visible,get", on_scrollbars_visible_get, app);
724     evas_object_smart_callback_add(app->browser, "menubar,visible,set", on_menubar_visible_set, app);
725     evas_object_smart_callback_add(app->browser, "menubar,visible,get", on_menubar_visible_get, app);
726     evas_object_smart_callback_add(app->browser, "tooltip,text,set", on_tooltip_text_set, app);
727     evas_object_smart_callback_add(app->browser, "inputmethod,changed", on_inputmethod_changed, app);
728     evas_object_smart_callback_add(app->browser, "uri,changed", on_url_changed, app);
729
730 /*     ewk_callback_resize_requested_add(app->browser, on_resize_requested, app->ee); */
731
732     evas_object_event_callback_add(app->browser, EVAS_CALLBACK_KEY_DOWN, on_key_down, app);
733     evas_object_event_callback_add(app->browser, EVAS_CALLBACK_MOUSE_DOWN, on_mouse_down, app);
734     evas_object_event_callback_add(app->browser, EVAS_CALLBACK_FOCUS_IN, on_focus_in, app);
735     evas_object_event_callback_add(app->browser, EVAS_CALLBACK_FOCUS_OUT, on_focus_out, app);
736     evas_object_event_callback_add(app->browser, EVAS_CALLBACK_DEL, on_browser_del, app);
737
738     app->url_bar = url_bar_add(app->browser, DEFAULT_WIDTH);
739
740     evas_object_move(app->browser, 0, URL_BAR_HEIGHT);
741     evas_object_resize(app->browser, geometry.w, geometry.h - URL_BAR_HEIGHT);
742
743     if (url && (url[0] != '\0'))
744         ewk_view_uri_set(app->browser, url);
745
746     evas_object_show(app->browser);
747     ecore_evas_show(app->ee);
748
749     evas_object_focus_set(app->browser, EINA_TRUE);
750
751     windows = eina_list_append(windows, app);
752
753     return 1;
754 }
755
756 static void
757 browserDestroy(Ecore_Evas *ee)
758 {
759     ecore_evas_free(ee);
760     if (!eina_list_count(windows))
761         ecore_main_loop_quit();
762 }
763
764 static void
765 closeWindow(Ecore_Evas *ee)
766 {
767     ELauncher *app;
768
769     app = find_app_from_ee(ee);
770     windows = eina_list_remove(windows, app);
771     url_bar_del(app->url_bar);
772     browserDestroy(ee);
773     free(app);
774 }
775
776 static Eina_Bool
777 main_signal_exit(void *data, int ev_type, void *ev)
778 {
779     ELauncher *app;
780     while (windows) {
781         app = (ELauncher*) eina_list_data_get(windows);
782         ecore_evas_free(app->ee);
783         windows = eina_list_remove(windows, app);
784     }
785     if (!eina_list_count(windows))
786         ecore_main_loop_quit();
787     return EINA_TRUE;
788 }
789
790 static char *
791 findThemePath(const char *theme)
792 {
793     const char *default_theme = THEME_DIR"/default.edj";
794     char *rpath;
795     struct stat st;
796
797     if (!theme)
798         theme = default_theme;
799
800     rpath = ecore_file_realpath(theme);
801     if (!strlen(rpath) || stat(rpath, &st)) {
802         free(rpath);
803         return NULL;
804     }
805
806     return rpath;
807 }
808
809 int
810 main(int argc, char *argv[])
811 {
812     const char *default_url = "http://www.google.com/";
813
814     Eina_Rectangle geometry = {0, 0, 0, 0};
815     char *userAgent = NULL;
816     const char *tmp;
817     const char *proxyUri;
818     char path[PATH_MAX];
819
820     char *engine = NULL;
821     char *theme = NULL;
822     char *backingStore = (char *)backingStores[1];
823
824     unsigned char quitOption = 0;
825     unsigned char isFlattening = 0;
826     unsigned char isFullscreen = 0;
827     int args;
828
829     Ecore_Getopt_Value values[] = {
830         ECORE_GETOPT_VALUE_STR(engine),
831         ECORE_GETOPT_VALUE_BOOL(quitOption),
832         ECORE_GETOPT_VALUE_STR(backingStore),
833         ECORE_GETOPT_VALUE_BOOL(isFlattening),
834         ECORE_GETOPT_VALUE_BOOL(isFullscreen),
835         ECORE_GETOPT_VALUE_PTR_CAST(geometry),
836         ECORE_GETOPT_VALUE_STR(theme),
837         ECORE_GETOPT_VALUE_STR(userAgent),
838         ECORE_GETOPT_VALUE_INT(verbose),
839         ECORE_GETOPT_VALUE_BOOL(quitOption),
840         ECORE_GETOPT_VALUE_BOOL(quitOption),
841         ECORE_GETOPT_VALUE_BOOL(quitOption),
842         ECORE_GETOPT_VALUE_BOOL(quitOption),
843         ECORE_GETOPT_VALUE_NONE
844     };
845
846     if (!ecore_evas_init())
847         return EXIT_FAILURE;
848
849     if (!edje_init()) {
850         ecore_evas_shutdown();
851         return EXIT_FAILURE;
852     }
853
854     if (!ecore_file_init()) {
855         edje_shutdown();
856         ecore_evas_shutdown();
857         return EXIT_FAILURE;
858     }
859
860     ecore_app_args_set(argc, (const char**) argv);
861     args = ecore_getopt_parse(&options, values, argc, argv);
862
863     if (args < 0)
864        return quit(EINA_FALSE, "ERROR: could not parse options.\n");
865
866     if (quitOption)
867         return quit(EINA_TRUE, NULL);
868
869     themePath = findThemePath(theme);
870     if (!themePath)
871         return quit(EINA_FALSE, "ERROR: could not find theme.\n");
872
873     ewk_init();
874     tmp = getenv("TMPDIR");
875     if (!tmp)
876         tmp = "/tmp";
877     snprintf(path, sizeof(path), "%s/.ewebkit-%u", tmp, getuid());
878     if (!ecore_file_mkpath(path))
879         return quit(EINA_FALSE, "ERROR: could not create settings database directory.\n");
880
881     ewk_settings_icon_database_path_set(path);
882     ewk_settings_web_database_path_set(path);
883
884     proxyUri = getenv("http_proxy");
885     if (proxyUri)
886         ewk_network_proxy_uri_set(proxyUri);
887
888     if (args < argc) {
889         char *url = url_from_user_input(argv[args]);
890         browserCreate(url, themePath, userAgent, geometry, engine, backingStore, isFlattening, isFullscreen, path);
891         free(url);
892     } else
893         browserCreate(default_url, themePath, userAgent, geometry, engine, backingStore, isFlattening, isFullscreen, path);
894
895     ecore_event_handler_add(ECORE_EVENT_SIGNAL_EXIT, main_signal_exit, &windows);
896
897     ecore_main_loop_begin();
898
899     ewk_shutdown();
900
901     return quit(EINA_TRUE, NULL);
902 }