[EFL] Remove unused function in MiniBrowser
[WebKit-https.git] / Tools / MiniBrowser / efl / main.c
1 /*
2  * Copyright (C) 2012 Samsung Electronics
3  * Copyright (C) 2012 Intel Corporation. All rights reserved.
4  *
5  *  This library is free software; you can redistribute it and/or
6  *  modify it under the terms of the GNU Lesser General Public
7  *  License as published by the Free Software Foundation; either
8  *  version 2 of the License, or (at your option) any later version.
9  *
10  *  This library is distributed in the hope that it will be useful,
11  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  *  Lesser General Public License for more details.
14  *
15  *  You should have received a copy of the GNU Lesser General Public
16  *  License along with this library; if not, write to the Free Software
17  *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
18  */
19
20 #include "EWebKit2.h"
21 #include <Ecore.h>
22 #include <Ecore_Evas.h>
23 #include <Ecore_Getopt.h>
24 #include <Eet.h>
25 #include <Eina.h>
26 #include <Elementary.h>
27 #include <Evas.h>
28
29 extern int efreet_cache_update;
30
31 static const char DEFAULT_URL[] = "http://www.ewebkit.org/";
32 static const char APP_NAME[] = "EFL MiniBrowser";
33 static const char JAVASCRIPT_SCHEME[] = "javascript:";
34 static const char FILE_SCHEME[] = "file://";
35 static const char HTTP_SCHEME[] = "http://";
36 static const int TOOL_BAR_ICON_SIZE = 24;
37 static const int TOOL_BAR_BUTTON_SIZE = 32;
38 static const int SEARCH_FIELD_SIZE = 200;
39 static const int SEARCH_BUTTON_SIZE = 30;
40 static const int MAX_SEARCH_COUNT = 1000;
41 static const double TOOLTIP_DELAY_SECONDS = 1.0;
42 static const double LONGPRESS_INTERVAL_SECONDS = 1.5;
43 static const double LIST_ITEM_HEIGHT = 24.35;
44
45 static Eina_List *windows = NULL;
46 static char *evas_engine_name = NULL;
47 static char *user_agent_string = NULL;
48 static char *extensions_path = NULL;
49 static char *background_color_string = NULL;
50 static Eina_Bool encoding_detector_enabled = EINA_FALSE;
51 static Eina_Bool frame_flattening_enabled = EINA_FALSE;
52 static Eina_Bool local_storage_enabled = EINA_TRUE;
53 static Eina_Bool offline_web_application_cache_enabled = EINA_TRUE;
54 static Eina_Bool fullscreen_enabled = EINA_FALSE;
55 static Eina_Bool spell_checking_enabled = EINA_FALSE;
56 static Eina_Bool web_security_enabled = EINA_TRUE;
57 static Eina_Bool touch_events_enabled = EINA_FALSE;
58 static Eina_Bool fixed_layout_enabled = EINA_TRUE;
59 static Eina_Bool separated_process_enabled = EINA_FALSE;
60 static Eina_Bool longpress_enabled = EINA_FALSE;
61 static int window_width = 1000;
62 static int window_height = 800;
63 static int color_picker_width = 350;
64 static int color_picker_height = 500;
65 static int search_flags = EWK_FIND_OPTIONS_SHOW_HIGHLIGHT | EWK_FIND_OPTIONS_WRAP_AROUND | EWK_FIND_OPTIONS_CASE_INSENSITIVE;
66 /* Default value of device_pixel_ratio is '0' so that we don't set custom device
67  * scale factor unless it's required by the User. */
68 static double device_pixel_ratio = 0;
69 static Eina_Bool legacy_behavior_enabled = EINA_FALSE;
70
71 #define DEFAULT_ZOOM_LEVEL 5 // Set default zoom level to 1.0 (index 5 on zoomLevels).
72 // The zoom values are chosen to be like in Mozilla Firefox 3.
73 const static float zoomLevels[] = {0.3, 0.5, 0.67, 0.8, 0.9, 1.0, 1.1, 1.2, 1.33, 1.5, 1.7, 2.0, 2.4, 3.0};
74 static int _log_domain_id = -1;
75
76 #define INFO(...) EINA_LOG_DOM_INFO(_log_domain_id, __VA_ARGS__)
77 #define ERROR(...) EINA_LOG_DOM_ERR(_log_domain_id, __VA_ARGS__)
78
79 static Eina_Bool
80 zoom_level_set(Evas_Object *webview, int level)
81 {
82    if (level < 0  || level >= sizeof(zoomLevels) / sizeof(float))
83      return EINA_FALSE;
84
85    return ewk_view_page_zoom_set(webview, zoomLevels[level]);
86 }
87
88 static Ewk_View_Smart_Class *miniBrowserViewSmartClass()
89 {
90    static Ewk_View_Smart_Class ewkViewClass = EWK_VIEW_SMART_CLASS_INIT_NAME_VERSION("MiniBrowser_View");
91    return &ewkViewClass;
92 }
93
94 typedef struct _Tooltip_Information {
95    Ecore_Timer *show_timer;
96    Eina_Bool activated;
97    Eina_Bool text_set;
98    Eina_Bool shown;
99 } Tooltip_Information;
100
101 typedef struct _Color_Selector {
102    Ewk_Color_Picker *ewk_picker;
103    Evas_Object *elm_selector;
104    Evas_Object *elm_selector_window;
105 } Color_Selector;
106
107 typedef struct _Browser_Window {
108    Evas_Object *elm_window;
109    Evas_Object *ewk_view;
110    Evas_Object *horizontal_layout;
111    Evas_Object *vertical_layout;
112    Evas_Object *url_bar;
113    Evas_Object *back_button;
114    Evas_Object *forward_button;
115    struct {
116      Evas_Object *elm_menu;
117      Ewk_Popup_Menu *ewk_menu;
118     } popup;
119    struct {
120      Evas_Object *search_bar;
121      Evas_Object *search_field;
122      Evas_Object *search_field_count;
123      Evas_Object *backward_button;
124      Evas_Object *forward_button;
125      Evas_Object *search_case_check_box;
126      Evas_Object *search_word_start_check_box;
127      Evas_Object *close_button;
128    } search;
129    struct {
130      Evas_Object *history_box;
131      Evas_Object *history_list;
132      Eina_List *history_list_items;
133    } history;
134    int current_zoom_level;
135    Tooltip_Information tooltip;
136    Color_Selector color_selector;
137    struct {
138      Evas_Object *elm_menu;
139      Ewk_Context_Menu *ewk_menu;
140    } context_menu;
141 } Browser_Window;
142
143 typedef struct _File_Selector_Data {
144    Browser_Window* parent;
145    Evas_Object *elm_window;
146    Ewk_File_Chooser_Request *request;
147 } File_Selector_Data;
148
149 typedef struct _Auth_Data {
150    Evas_Object *popup;
151    Ewk_Auth_Request *request;
152    Evas_Object *username_entry;
153    Evas_Object *password_entry;
154 } Auth_Data;
155
156 static const Ecore_Getopt options = {
157    "MiniBrowser",
158    "%prog [options] [url]",
159    "0.0.1",
160    "(C)2012 Samsung Electronics\n (C)2012 Intel Corporation\n",
161    "",
162    "Test Web Browser using the Enlightenment Foundation Libraries (EFL) port of WebKit2",
163    EINA_TRUE, {
164      ECORE_GETOPT_STORE_STR
165          ('e', "engine", "Ecore-evas engine to use."),
166      ECORE_GETOPT_STORE_STR
167          ('s', "window-size", "Window size in following format (width)x(height)."),
168      ECORE_GETOPT_STORE_STR
169          ('u', "user-agent", "User agent to set."),
170      ECORE_GETOPT_STORE_STR
171          ('x', "extensions-path", "The path which extensions are stored."),
172      ECORE_GETOPT_STORE_DOUBLE
173          ('r', "device-pixel-ratio", "Ratio between the CSS units and device pixels."),
174      ECORE_GETOPT_CALLBACK_NOARGS
175          ('E', "list-engines", "List ecore-evas engines.",
176           ecore_getopt_callback_ecore_evas_list_engines, NULL),
177      ECORE_GETOPT_STORE_DEF_BOOL
178          ('c', "encoding-detector", "Enable/disable encoding detector.", EINA_FALSE),
179      ECORE_GETOPT_STORE_STR
180          ('C', "background-color", "Background color of page. ex) -C=255:255:255:255"),
181      ECORE_GETOPT_STORE_DEF_BOOL
182          ('f', "flattening", "Enable/disable frame flattening.", EINA_FALSE),
183      ECORE_GETOPT_STORE_DEF_BOOL
184          ('l', "local-storage", "Enable/disable HTML5 local storage.", EINA_TRUE),
185      ECORE_GETOPT_STORE_DEF_BOOL
186          ('o', "offline-web-application-cache", "Enable/disable offline web application cache.", EINA_TRUE),
187      ECORE_GETOPT_STORE_DEF_BOOL
188          ('F', "full-screen", "Start in full-screen.", EINA_FALSE),
189      ECORE_GETOPT_STORE_DEF_BOOL
190          ('t', "text-checking", "Enable/disable text spell checking.", EINA_FALSE),
191      ECORE_GETOPT_STORE_DEF_BOOL
192          ('T', "touch-events", "Enable/disable touch events.", EINA_FALSE),
193      ECORE_GETOPT_STORE_DEF_BOOL
194          ('L', "fixed-layout", "Enable/disable fixed layout.", EINA_TRUE),
195      ECORE_GETOPT_STORE_DEF_STR
196          ('p', "policy-cookies", "Cookies policy:\n  always - always accept,\n  never - never accept,\n  no-third-party - don't accept third-party cookies.", "no-third-party"),
197      ECORE_GETOPT_STORE_DEF_BOOL
198          ('w', "web-security", "enable/disable web security.", EINA_TRUE),
199      ECORE_GETOPT_STORE_DEF_BOOL
200          ('S', "separate-process", "Create new window in separated web process.", EINA_FALSE),
201      ECORE_GETOPT_VERSION
202          ('V', "version"),
203      ECORE_GETOPT_COPYRIGHT
204          ('R', "copyright"),
205      ECORE_GETOPT_HELP
206          ('h', "help"),
207      ECORE_GETOPT_SENTINEL
208    }
209 };
210
211 static Eina_Stringshare *_file_entry_dialog_show(Browser_Window *window, const char *label_tag, const char *default_text);
212 static Browser_Window *window_create(Ewk_View_Configuration* configuration, int width, int height);
213 static Ewk_View_Configuration* configuration();
214
215 static Browser_Window *window_find_with_ewk_view(Evas_Object *ewk_view)
216 {
217    Eina_List *l;
218    void *data;
219
220    if (!ewk_view)
221      return NULL;
222
223    EINA_LIST_FOREACH(windows, l, data) {
224      Browser_Window *window = (Browser_Window *)data;
225      if (window->ewk_view == ewk_view)
226        return window;
227    }
228    return NULL;
229 }
230
231 static Eina_Bool
232 _tooltip_show(void *user_data)
233 {
234    Browser_Window *window = (Browser_Window *)user_data;
235
236    window->tooltip.show_timer = NULL;
237    elm_object_tooltip_show(window->elm_window);
238    window->tooltip.shown = EINA_TRUE;
239    return ECORE_CALLBACK_CANCEL;
240 }
241
242 static void
243 window_tooltip_hide(Browser_Window *window)
244 {
245    if (window->tooltip.show_timer) {
246      ecore_timer_del(window->tooltip.show_timer);
247      window->tooltip.show_timer = NULL;
248    }
249
250    if (window->tooltip.shown) {
251      elm_object_tooltip_hide(window->elm_window);
252      window->tooltip.shown = EINA_FALSE;
253    }
254 }
255
256 static void
257 window_tooltip_update(Browser_Window *window)
258 {
259    window_tooltip_hide(window);
260
261    if (window->tooltip.activated && window->tooltip.text_set)
262      window->tooltip.show_timer = ecore_timer_add(TOOLTIP_DELAY_SECONDS, _tooltip_show, window);
263 }
264
265 static void
266 _mouse_in_cb(void *user_data, Evas *e, Evas_Object *ewk_view, void *event_info)
267 {
268    Browser_Window *window = (Browser_Window *)user_data;
269
270    window->tooltip.activated = EINA_TRUE;
271    window_tooltip_update(window);
272 }
273
274 static void
275 _mouse_move_cb(void *user_data, Evas *e, Evas_Object *ewk_view, void *event_info)
276 {
277    window_tooltip_update((Browser_Window *)user_data);
278 }
279
280 static void
281 _mouse_out_cb(void *user_data, Evas *e, Evas_Object *ewk_view, void *event_info)
282 {
283    Browser_Window *window = (Browser_Window *)user_data;
284
285    window->tooltip.activated = EINA_FALSE;
286    window_tooltip_update(window);
287 }
288
289 static void
290 _mouse_wheel_cb(void *user_data, Evas *e, Evas_Object *ewk_view, void *event_info)
291 {
292    Browser_Window *window = (Browser_Window *)user_data;
293    const Evas_Modifier *mod = evas_key_modifier_get(e);
294    Evas_Event_Mouse_Wheel *ev = (Evas_Event_Mouse_Wheel *)event_info;
295    Eina_Bool shiftPressed = evas_key_modifier_is_set(mod, "Shift");
296    Eina_Bool ctrlPressed = evas_key_modifier_is_set(mod, "Control");
297
298    if (!shiftPressed && !ctrlPressed)
299      return;
300
301    /* navigate history or zoom web page based on mouse wheel scroll action with shift or control key */
302    if (shiftPressed) {
303      if (ev->z == -1 && ewk_view_forward_possible(ewk_view)) {
304        ewk_view_forward(ewk_view);
305        elm_object_disabled_set(window->forward_button, !ewk_view_forward_possible(ewk_view));
306      } else if (ev->z == 1 && ewk_view_back_possible(ewk_view)) {
307        ewk_view_back(ewk_view);
308        elm_object_disabled_set(window->back_button, !ewk_view_back_possible(ewk_view));
309      }
310    } else if (ctrlPressed) {
311      if (ev->z == -1 && zoom_level_set(ewk_view, window->current_zoom_level + 1)) {
312        window->current_zoom_level++;
313        INFO("Zoom in (Ctrl + 'scroll up') was pressed, zoom level became %.2f", zoomLevels[window->current_zoom_level]);
314      } else if (ev->z == 1 && zoom_level_set(ewk_view, window->current_zoom_level - 1)) {
315        window->current_zoom_level--;
316        INFO("Zoom out (Ctrl + 'scroll down') was pressed, zoom level became %.2f", zoomLevels[window->current_zoom_level]);
317      }
318    }
319 }
320
321 static void
322 _window_resize_cb(void *user_data, Evas *e, Evas_Object *elm_window, void *event_info)
323 {
324    Browser_Window *window = (Browser_Window *)user_data;
325
326    if (!window) {
327      ERROR("Window is NULL.");
328      return;
329    }
330
331    if (window->context_menu.ewk_menu)
332      ewk_context_menu_hide(window->context_menu.ewk_menu);
333    if (window->popup.ewk_menu)
334      ewk_popup_menu_close(window->popup.ewk_menu);
335    if (window->popup.elm_menu)
336      elm_menu_close(window->popup.elm_menu);
337 }
338
339 static void
340 update_view_favicon(Browser_Window *window, Evas_Object *icon)
341 {
342    /* Remove previous icon from URL bar */
343    Evas_Object *old_icon = elm_object_part_content_unset(window->url_bar, "icon");
344    if (old_icon) {
345      evas_object_unref(old_icon);
346      evas_object_del(old_icon);
347    }
348
349    /* Show new icon in URL bar */
350    if (icon) {
351      evas_object_size_hint_min_set(icon, 32, 32);
352      elm_object_part_content_set(window->url_bar, "icon", icon);
353      evas_object_ref(icon);
354    }
355 }
356
357 static void
358 _icon_changed_cb(Ewk_Favicon_Database *database, const char *url, void *user_data)
359 {
360    Browser_Window *window = (Browser_Window *)user_data;
361    Evas_Object *ewk_view = window->ewk_view;
362
363    if (strcmp(url, ewk_view_url_get(ewk_view)))
364      return;
365
366    Evas_Object *favicon = ewk_favicon_database_icon_get(database, url, evas_object_evas_get(ewk_view));
367    update_view_favicon(window, favicon);
368
369    if (favicon)
370      evas_object_unref(favicon);
371 }
372
373 static void window_free(Browser_Window *window)
374 {
375    evas_object_event_callback_del(window->ewk_view, EVAS_CALLBACK_MOUSE_IN, _mouse_in_cb);
376    evas_object_event_callback_del(window->ewk_view, EVAS_CALLBACK_MOUSE_OUT, _mouse_out_cb);
377    evas_object_event_callback_del(window->ewk_view, EVAS_CALLBACK_MOUSE_MOVE, _mouse_move_cb);
378    evas_object_event_callback_del(window->ewk_view, EVAS_CALLBACK_MOUSE_WHEEL, _mouse_wheel_cb);
379
380    evas_object_event_callback_del(window->elm_window, EVAS_CALLBACK_RESIZE, _window_resize_cb);
381
382    ewk_favicon_database_icon_change_callback_del(ewk_context_favicon_database_get(ewk_view_context_get(window->ewk_view)), _icon_changed_cb);
383
384    evas_object_del(window->ewk_view);
385    /* The elm_win will take care of freeing its children */
386    evas_object_del(window->elm_window);
387
388    if (window->tooltip.show_timer)
389      ecore_timer_del(window->tooltip.show_timer);
390
391    if (window->color_selector.elm_selector_window)
392      evas_object_del(window->color_selector.elm_selector_window);
393
394    free(window);
395 }
396
397 static void window_close(Browser_Window *window)
398 {
399    windows = eina_list_remove(windows, window);
400    window_free(window);
401
402    if (!windows)
403      elm_exit();
404 }
405
406 static void
407 search_icon_show(Browser_Window *window)
408 {
409    Evas_Object *icon = elm_icon_add(window->elm_window);
410    elm_icon_standard_set(icon, "edit-find");
411    elm_object_part_content_set(window->search.search_field, "icon", icon);
412    evas_object_size_hint_min_set(icon, 20, 20);
413    evas_object_size_hint_max_set(icon, 20, 20);
414    elm_entry_icon_visible_set(window->search.search_field, EINA_TRUE);
415    evas_object_show(icon);
416 }
417
418 static void
419 search_box_show(Browser_Window *window)
420 {
421    evas_object_size_hint_min_set(window->search.search_bar, SEARCH_FIELD_SIZE + 2 * SEARCH_BUTTON_SIZE, SEARCH_BUTTON_SIZE);
422
423    search_icon_show(window);
424    evas_object_show(window->search.search_bar);
425    evas_object_show(window->search.search_field);
426    evas_object_show(window->search.search_field_count);
427    evas_object_show(window->search.backward_button);
428    evas_object_show(window->search.forward_button);
429    evas_object_show(window->search.search_case_check_box);
430    evas_object_show(window->search.search_word_start_check_box);
431    evas_object_show(window->search.close_button);
432
433    /* Grab focus from the view */
434    evas_object_focus_set(window->ewk_view, EINA_FALSE);
435    elm_object_focus_set(window->search.search_field, EINA_TRUE);
436 }
437
438 static void
439 search_box_hide(Browser_Window *window)
440 {
441    ewk_view_text_find_highlight_clear(window->ewk_view);
442
443    evas_object_size_hint_min_set(window->search.search_bar, SEARCH_FIELD_SIZE + 2 * SEARCH_BUTTON_SIZE, 0);
444    evas_object_hide(window->search.search_bar);
445    evas_object_hide(window->search.search_field);
446    evas_object_hide(window->search.search_field_count);
447    evas_object_hide(window->search.backward_button);
448    evas_object_hide(window->search.forward_button);
449    evas_object_hide(window->search.search_case_check_box);
450    evas_object_hide(window->search.search_word_start_check_box);
451    evas_object_hide(window->search.close_button);
452
453    /* Give focus back to the view */
454    elm_object_focus_set(window->search.search_field, EINA_FALSE);
455    evas_object_focus_set(window->ewk_view, EINA_TRUE);
456 }
457
458 static void
459 history_list_hide(Browser_Window *window)
460 {
461    /* Hide history list */
462    evas_object_hide(window->history.history_box);
463    evas_object_hide(window->history.history_list);
464
465    /* Dereference the list items and clear the history list */
466    void *data;
467    EINA_LIST_FREE(window->history.history_list_items, data) {
468        ewk_object_unref(data);
469    }
470
471    elm_genlist_clear(window->history.history_list);
472
473    /* Give focus back to the view */
474    elm_object_focus_set(window->history.history_box, EINA_FALSE);
475    elm_object_focus_set(window->history.history_list, EINA_FALSE);
476    evas_object_focus_set(window->ewk_view, EINA_TRUE);
477
478    /* Reset flags */
479    longpress_enabled = EINA_FALSE;
480 }
481
482 static void save_page_contents_callback(Ewk_Page_Contents_Type type, const char *data, void *user_data)
483 {
484    Eet_File *ef;
485    Eina_Stringshare *fileName = (Eina_Stringshare *)user_data;
486
487    if (!eina_str_has_extension(fileName, ".mht")) {
488      Eina_Strbuf *fileNameWithMht = eina_strbuf_new();
489      eina_strbuf_append_printf(fileNameWithMht, "%s.mht", fileName);
490      ef = eet_open(eina_strbuf_string_get(fileNameWithMht), EET_FILE_MODE_WRITE);
491      INFO("Saving file to: %s", eina_strbuf_string_get(fileNameWithMht));
492      eina_strbuf_free(fileNameWithMht);
493    } else {
494      ef = eet_open(fileName, EET_FILE_MODE_WRITE);
495      INFO("Saving file to: %s", fileName);
496    }
497
498    if (!ef) {
499      ERROR("Could not create File");
500      return;
501    }
502
503    eet_write(ef, "MHTML data", data, strlen(data), 0 /* compress */);
504    eet_close(ef);
505    INFO("SUCCESS: saved.");
506
507    eina_stringshare_del(fileName);
508 }
509
510 static void
511 script_execute_callback(Evas_Object *ewk_view, const char *return_value, void *user_data)
512 {
513    Browser_Window *window = (Browser_Window *)user_data;
514
515    Eina_Strbuf *text_buffer = eina_strbuf_new();
516
517    if (return_value) {
518      eina_strbuf_append(text_buffer, return_value);
519      INFO("selected text is: %s", eina_strbuf_string_get(text_buffer));
520      elm_entry_entry_set(window->search.search_field, eina_strbuf_string_get(text_buffer));
521    }
522    eina_strbuf_free(text_buffer);
523    search_box_show(window);
524 }
525
526 static void
527 toggle_window_fullscreen(Browser_Window *window, Eina_Bool isFullScreen)
528 {
529    if (isFullScreen) {
530      evas_object_hide(window->horizontal_layout);
531      elm_box_unpack(window->vertical_layout, window->horizontal_layout);
532      elm_win_fullscreen_set(window->elm_window, EINA_TRUE);
533    } else {
534      elm_win_fullscreen_set(window->elm_window, EINA_FALSE);
535      elm_box_pack_start(window->vertical_layout, window->horizontal_layout);
536       evas_object_show(window->horizontal_layout);
537    }
538 }
539
540 static void
541 _key_down_cb(void *user_data, Evas *e, Evas_Object *ewk_view, void *event_info)
542 {
543    Browser_Window *window = (Browser_Window *)user_data;
544    Evas_Event_Key_Down *ev = (Evas_Event_Key_Down*) event_info;
545
546    static const char *encodings[] = {
547      "ISO-8859-1",
548      "UTF-8",
549      NULL
550    };
551    static int currentEncoding = -1;
552    const Evas_Modifier *mod = evas_key_modifier_get(e);
553    Eina_Bool ctrlPressed = evas_key_modifier_is_set(mod, "Control");
554    Eina_Bool altPressed = evas_key_modifier_is_set(mod, "Alt");
555    Eina_Bool shiftPressed = evas_key_modifier_is_set(mod, "Shift");
556
557    if (!strcmp(ev->key, "Left") && altPressed) {
558      INFO("Back (Alt+Left) was pressed");
559      if (!ewk_view_back(ewk_view))
560        INFO("Back ignored: No back history");
561    } else if (!strcmp(ev->key, "Right") && altPressed) {
562      INFO("Forward (Alt+Right) was pressed");
563      if (!ewk_view_forward(ewk_view))
564        INFO("Forward ignored: No forward history");
565    } else if (!strcmp(ev->key, "Home") && altPressed) {
566      INFO("Home (Alt+Home) was pressed");
567      ewk_view_url_set(window->ewk_view, DEFAULT_URL);
568    } else if (!strcmp(ev->key, "F3")) {
569      currentEncoding = (currentEncoding + 1) % (sizeof(encodings) / sizeof(encodings[0]));
570      INFO("Set encoding (F3) pressed. New encoding to %s", encodings[currentEncoding]);
571      ewk_view_custom_encoding_set(ewk_view, encodings[currentEncoding]);
572    } else if ((!strcmp(ev->key, "F5") && ctrlPressed) || (!strcmp(ev->key, "r") && (shiftPressed & ctrlPressed))) {
573      INFO("Reload ignoring cache (Ctrl+F5 or Ctrl+Shift+r) was pressed, reloading and bypassing cache...");
574      ewk_view_reload_bypass_cache(ewk_view);
575    } else if (!strcmp(ev->key, "F5") || (!strcmp(ev->key, "r") && ctrlPressed)) {
576      INFO("Reload (F5 or Ctrl+r) was pressed, reloading...");
577      ewk_view_reload(ewk_view);
578    } else if (!strcmp(ev->key, "F6")) {
579      INFO("Stop (F6) was pressed, stop loading.");
580      ewk_view_stop(ewk_view);
581    } else if (!strcmp(ev->key, "F7")) {
582      Ewk_Pagination_Mode mode =  ewk_view_pagination_mode_get(ewk_view);
583      mode = (mode + 1) % (EWK_PAGINATION_MODE_BOTTOM_TO_TOP + 1);
584      if (ewk_view_pagination_mode_set(ewk_view, mode))
585        INFO("Change Pagination Mode (F7) was pressed, changed to: %d", mode);
586      else
587        INFO("Change Pagination Mode (F7) was pressed, but NOT changed!");
588    } else if (!strcmp(ev->key, "F11")) {
589      INFO("Fullscreen (F11) was pressed, toggling window/fullscreen.");
590      toggle_window_fullscreen(window, !elm_win_fullscreen_get(window->elm_window));
591    } else if (!strcmp(ev->key, "n") && ctrlPressed) {
592      INFO("Create new window (Ctrl+n) was pressed.");
593      Browser_Window *window = window_create(configuration(), 0, 0);
594      ewk_view_url_set(window->ewk_view, DEFAULT_URL);
595      // 0 equals default width and height.
596      windows = eina_list_append(windows, window);
597    } else if (!strcmp(ev->key, "i") && ctrlPressed) {
598      INFO("Show Inspector (Ctrl+i) was pressed.");
599      ewk_view_inspector_show(ewk_view);
600    } else if (!strcmp(ev->key, "f") && ctrlPressed) {
601      INFO("Show Search Box (Ctrl+f) was pressed.");
602      const char get_data_script[] = "window.getSelection().toString();";
603      ewk_view_script_execute(ewk_view, get_data_script, script_execute_callback, (void*)(window));
604    } else if (!strcmp(ev->key, "Escape")) {
605      if (evas_object_visible_get(window->search.search_bar))
606        search_box_hide(window);
607      else if (evas_object_visible_get(window->history.history_box))
608        history_list_hide(window);
609      else if (elm_win_fullscreen_get(window->elm_window))
610        ewk_view_fullscreen_exit(ewk_view);
611      else
612        ewk_view_stop(ewk_view);
613    } else if (ctrlPressed && (!strcmp(ev->key, "minus") || !strcmp(ev->key, "KP_Subtract"))) {
614      if (zoom_level_set(ewk_view, window->current_zoom_level - 1))
615        window->current_zoom_level--;
616      INFO("Zoom out (Ctrl + '-') was pressed, zoom level became %.2f", zoomLevels[window->current_zoom_level]);
617    } else if (ctrlPressed && (!strcmp(ev->key, "equal") || !strcmp(ev->key, "KP_Add"))) {
618      if (zoom_level_set(ewk_view, window->current_zoom_level + 1))
619        window->current_zoom_level++;
620      INFO("Zoom in (Ctrl + '+') was pressed, zoom level became %.2f", zoomLevels[window->current_zoom_level]);
621    } else if (ctrlPressed && !strcmp(ev->key, "0")) {
622      if (zoom_level_set(ewk_view, DEFAULT_ZOOM_LEVEL))
623        window->current_zoom_level = DEFAULT_ZOOM_LEVEL;
624      INFO("Zoom to default (Ctrl + '0') was pressed, zoom level became %.2f", zoomLevels[window->current_zoom_level]);
625    } else if (ctrlPressed && !strcmp(ev->key, "s")) {
626      Eina_Strbuf *default_file = eina_strbuf_new();
627      const char *home_path = getenv("HOME");
628      const char *title = ewk_view_title_get(window->ewk_view);
629      eina_strbuf_append_printf(default_file, "%s/%s.mht", home_path ? home_path : "/home", title ? title : "title");
630      INFO("Pressed (CTRL + S) : Saving Current Page.");
631      Eina_Stringshare *save_file_name = _file_entry_dialog_show(window, "SAVE", eina_strbuf_string_get(default_file));
632      if (!save_file_name)
633        return;
634      ewk_view_page_contents_get(ewk_view, EWK_PAGE_CONTENTS_TYPE_MHTML, save_page_contents_callback, (void *)save_file_name);
635      eina_strbuf_free(default_file);
636    } else if (ctrlPressed && !strcmp(ev->key, "l")) {
637      const char *home_path =  getenv("HOME");
638      Eina_Stringshare *open_file_name = _file_entry_dialog_show(window, "LOAD", home_path ? home_path : "/home");
639      if (!open_file_name)
640        return;
641      Eina_Strbuf *uri_path = eina_strbuf_new();
642      eina_strbuf_append_printf(uri_path, "%s%s", FILE_SCHEME, open_file_name);
643      INFO("pressed (CTRL + L) : Loading Page %s", eina_strbuf_string_get(uri_path));
644      ewk_view_url_set(ewk_view, eina_strbuf_string_get(uri_path));
645      eina_strbuf_free(uri_path);
646      eina_stringshare_del(open_file_name);
647    }
648 }
649
650 static void
651 view_focus_set(Browser_Window *window, Eina_Bool focus)
652 {
653    /* We steal focus away from elm's focus model and start to do things
654     * manually here, so elm now has no clue what's up. Tell elm that its
655     * toplevel widget is to be unfocused so elm gives up the focus */
656    elm_object_focus_set(elm_object_top_widget_get(window->elm_window), EINA_FALSE);
657    evas_object_focus_set(window->ewk_view, focus);
658 }
659
660 static void
661 _mouse_down_cb(void *user_data, Evas *e, Evas_Object *ewk_view, void *event_info)
662 {
663    Browser_Window *window = (Browser_Window *)user_data;
664    Evas_Event_Mouse_Down *ev = (Evas_Event_Mouse_Down *)event_info;
665
666    /* Clear selection from the URL bar */
667    elm_entry_select_none(window->url_bar);
668
669    if (longpress_enabled)
670      history_list_hide(window);
671    if (ev->button == 1)
672      view_focus_set(window, EINA_TRUE);
673    else if (ev->button == 2)
674      view_focus_set(window, !evas_object_focus_get(ewk_view));
675 }
676
677 static void
678 title_set(Evas_Object *elm_window, const char *title, int progress)
679 {
680    Eina_Strbuf *buffer;
681
682    if (!title || !*title) {
683      elm_win_title_set(elm_window, APP_NAME);
684      return;
685    }
686
687    buffer = eina_strbuf_new();
688    if (progress < 100)
689      eina_strbuf_append_printf(buffer, "%s (%d%%) - %s", title, progress, APP_NAME);
690    else
691      eina_strbuf_append_printf(buffer, "%s - %s", title, APP_NAME);
692
693    elm_win_title_set(elm_window, eina_strbuf_string_get(buffer));
694    eina_strbuf_free(buffer);
695 }
696
697 static void
698 _title_changed_cb(void *user_data, Evas_Object *ewk_view, void *event_info)
699 {
700    Browser_Window *window = (Browser_Window *)user_data;
701    const char *title = (const char *)event_info;
702
703    title_set(window->elm_window, title, 100);
704 }
705
706 static void
707 _url_changed_cb(void *user_data, Evas_Object *ewk_view, void *event_info)
708 {
709    Browser_Window *window = (Browser_Window *)user_data;
710    const char *url = ewk_view_url_get(window->ewk_view);
711    char *converted_url = elm_entry_utf8_to_markup(url);
712    elm_entry_entry_set(window->url_bar, converted_url);
713
714    _icon_changed_cb(ewk_context_favicon_database_get(ewk_view_context_get(ewk_view)), url, user_data);
715
716    free(converted_url);
717
718    search_box_hide(window);
719 }
720
721 static void
722 _back_forward_list_changed_cb(void *user_data, Evas_Object *ewk_view, void *event_info)
723 {
724    Browser_Window *window = (Browser_Window *)user_data;
725
726    /* Update navigation buttons state */
727    elm_object_disabled_set(window->back_button, !ewk_view_back_possible(ewk_view));
728    elm_object_disabled_set(window->forward_button, !ewk_view_forward_possible(ewk_view));
729 }
730
731 static void
732 _progress_cb(void *user_data, Evas_Object *ewk_view, void *event_info)
733 {
734    Browser_Window *window = (Browser_Window *)user_data;
735    double progress = *(double *)event_info;
736
737    title_set(window->elm_window, ewk_view_title_get(window->ewk_view), progress * 100);
738 }
739
740 static void
741 _error_cb(void *user_data, Evas_Object *ewk_view, void *event_info)
742 {
743    Eina_Strbuf *buffer;
744    const Ewk_Error *error = (const Ewk_Error *)event_info;
745
746    /* This is a cancellation, do not display the error page */
747    if (ewk_error_cancellation_get(error))
748      return;
749
750    buffer = eina_strbuf_new();
751    eina_strbuf_append_printf(buffer,
752      "<html><body><div style=\"color:#ff0000\">ERROR!</div><br><div>Code: %d<br>Description: %s<br>URL: %s</div></body</html>",
753      ewk_error_code_get(error), ewk_error_description_get(error), ewk_error_url_get(error));
754
755    ewk_view_html_string_load(ewk_view, eina_strbuf_string_get(buffer), 0, ewk_error_url_get(error));
756    eina_strbuf_free(buffer);
757 }
758
759 static void
760 _download_request_cb(Ewk_Download_Job *download, void *user_data)
761 {
762    Browser_Window *window = (Browser_Window *)user_data;
763
764    Eina_Strbuf *destination_path = eina_strbuf_new();
765
766    const char *home_path = getenv("HOME");
767    Eina_Stringshare *save_file_path = _file_entry_dialog_show(window, "DOWNLOAD", home_path ? home_path : "/tmp");
768
769    if (save_file_path)
770      eina_strbuf_append_printf(destination_path, "%s", save_file_path);
771    else
772      eina_strbuf_append(destination_path, "/tmp");
773
774    const char *suggested_name = ewk_download_job_suggested_filename_get(download);
775    if (suggested_name && *suggested_name)
776      eina_strbuf_append_printf(destination_path, "/%s", suggested_name);
777    else {
778      // Generate a unique file name since no name was suggested.
779      eina_strbuf_append(destination_path, "/downloaded-file.XXXXXX");
780      char *url = NULL;
781      url = eina_strbuf_string_steal(destination_path);
782      if (mkstemp(url) == -1) {
783        ERROR("Could not generate a unique file name.");
784        return;
785      }
786      eina_strbuf_append(destination_path, url);
787    }
788
789    ewk_download_job_destination_set(download, eina_strbuf_string_get(destination_path));
790    INFO("Downloading: %s", eina_strbuf_string_get(destination_path));
791    eina_strbuf_free(destination_path);
792    eina_stringshare_del(save_file_path);
793 }
794
795 static void _filepicker_parent_deletion_cb(void *user_data, Evas *evas, Evas_Object *elm_window, void *event);
796
797 static void close_file_picker(File_Selector_Data *fs_data)
798 {
799    evas_object_event_callback_del(fs_data->parent->elm_window, EVAS_CALLBACK_DEL, _filepicker_parent_deletion_cb);
800    evas_object_del(fs_data->elm_window);
801    ewk_object_unref(fs_data->request);
802    free(fs_data);
803 }
804
805 static void
806 _filepicker_parent_deletion_cb(void *user_data, Evas *evas, Evas_Object *elm_window, void *event)
807 {
808    close_file_picker((File_Selector_Data *)user_data);
809 }
810
811 static void
812 _filepicker_deletion_cb(void *user_data, Evas_Object *elm_window, void *event_info)
813 {
814    close_file_picker((File_Selector_Data *)user_data);
815 }
816
817 static void
818 _fileselector_done_cb(void *user_data, Evas_Object *file_selector, void *event_info)
819 {
820    File_Selector_Data *fs_data = (File_Selector_Data *)user_data;
821
822    const char *selected = (const char *)event_info;
823    if (selected && *selected)
824      ewk_file_chooser_request_file_choose(fs_data->request, selected);
825
826    close_file_picker(fs_data);
827 }
828
829 static void
830 _file_chooser_request_cb(void *user_data, Evas_Object *ewk_view, void *event_info)
831 {
832    Evas_Object *bg;
833    Browser_Window *window = (Browser_Window *)user_data;
834    Ewk_File_Chooser_Request *request = (Ewk_File_Chooser_Request *)event_info;
835
836    // Show basic file picker which does not currently support multiple files
837    // or MIME type filtering.
838    Evas_Object *elm_window = elm_win_add(window->elm_window, "file-picker-window", ELM_WIN_DIALOG_BASIC);
839    elm_win_title_set(elm_window, "File picker");
840    elm_win_modal_set(elm_window, EINA_TRUE);
841
842    bg = elm_bg_add(elm_window);
843    evas_object_size_hint_weight_set(bg, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
844    elm_win_resize_object_add(elm_window, bg);
845    evas_object_show(bg);
846
847    File_Selector_Data *fs_data = (File_Selector_Data *)malloc(sizeof(File_Selector_Data));
848    fs_data->parent = window;
849    fs_data->elm_window = elm_window;
850    fs_data->request = ewk_object_ref(request);
851    evas_object_smart_callback_add(elm_window, "delete,request", _filepicker_deletion_cb, fs_data);
852    evas_object_event_callback_add(window->elm_window, EVAS_CALLBACK_DEL, _filepicker_parent_deletion_cb, fs_data);
853
854    Evas_Object *file_selector = elm_fileselector_add(elm_window);
855    const char *home_path = getenv("HOME");
856    elm_fileselector_path_set(file_selector, home_path ? home_path : "/home");
857    evas_object_size_hint_weight_set(file_selector, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
858    elm_win_resize_object_add(elm_window, file_selector);
859    evas_object_show(file_selector);
860
861    evas_object_smart_callback_add(file_selector, "done", _fileselector_done_cb, fs_data);
862
863    int x, y, width, height;
864    evas_object_geometry_get(window->elm_window, &x, &y, &width, &height);
865
866    int picker_x = x + width / 2 - color_picker_width / 2;
867    int picker_y = y + height / 2 - color_picker_height / 2;
868    evas_object_geometry_set(window->color_selector.elm_selector_window, picker_x, picker_y,
869      color_picker_width, color_picker_height);
870 }
871
872 static void
873 _download_finished_cb(Ewk_Download_Job *download, void *user_data)
874 {
875    INFO("Download finished: %s",  ewk_download_job_destination_get(download));
876 }
877
878 static void
879 _download_failed_cb(Ewk_Download_Job_Error *download_error, void *user_data)
880 {
881    Ewk_Error *error = download_error->error;
882
883    INFO("Download failed! Error code: %d, Error description: %s, Error URL: %s", ewk_error_code_get(error), ewk_error_description_get(error), ewk_error_url_get(error));
884 }
885
886 static void
887 _color_changed_cb(void *data, Evas_Object *obj, void *event_info)
888 {
889    int r, g, b, a;
890
891    elm_colorselector_color_get(obj, &r, &g, &b, &a);
892    evas_object_color_set(data, r, g, b, a);
893 }
894
895 static void
896 _color_item_selected_cb(void *data, Evas_Object *obj, void *event_info)
897 {
898    int r, g, b, a;
899    Elm_Object_Item *color_item = (Elm_Object_Item *)event_info;
900
901    elm_colorselector_palette_item_color_get(color_item, &r, &g, &b, &a);
902    evas_object_color_set(data, r, g, b, a);
903 }
904
905 static void
906 _color_picker_ok_clicked_cb(void *data, Evas_Object *obj, void *event_info)
907 {
908    int r, g, b, a;
909    Color_Selector *color_selector = (Color_Selector *)data;
910
911    elm_colorselector_color_get(color_selector->elm_selector, &r, &g, &b, &a);
912    ewk_color_picker_color_set(color_selector->ewk_picker, r, g, b, a);
913 }
914
915 static void
916 _color_picker_cancel_clicked_cb(void *data, Evas_Object *obj, void *event_info)
917 {
918    int r, g, b, a;
919
920    ewk_color_picker_color_get(data, &r, &g, &b, &a);
921    ewk_color_picker_color_set(data, r, g, b, a);
922 }
923
924 static Eina_Bool
925 _color_picker_dismiss_cb(Ewk_View_Smart_Data *sd)
926 {
927    Browser_Window *window = window_find_with_ewk_view(sd->self);
928
929    evas_object_del(window->color_selector.elm_selector_window);
930    window->color_selector.elm_selector_window = NULL;
931
932    return EINA_TRUE;
933 }
934
935 static Eina_Bool
936 _color_picker_request_cb(Ewk_View_Smart_Data *sd, Ewk_Color_Picker *color_picker)
937 {
938    int r, g, b, a;
939    Evas_Object *background, *rect, *box, *button_box, *rect_frame, *cs_frame, *ok_button, *cancel_button;
940
941    Browser_Window *window = window_find_with_ewk_view(sd->self);
942    window->color_selector.elm_selector_window = elm_win_add(window->elm_window, "color selector", ELM_WIN_BASIC);
943    window->color_selector.ewk_picker = color_picker;
944
945    elm_win_title_set(window->color_selector.elm_selector_window, "Color selector");
946
947    /* Show color view */
948    background = elm_bg_add(window->color_selector.elm_selector_window);
949    evas_object_size_hint_weight_set(background, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
950    elm_win_resize_object_add(window->color_selector.elm_selector_window, background);
951    evas_object_show(background);
952
953    box = elm_box_add(window->color_selector.elm_selector_window);
954    evas_object_size_hint_weight_set(box, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
955    elm_win_resize_object_add(window->color_selector.elm_selector_window, box);
956    evas_object_show(box);
957
958    rect_frame = elm_frame_add(window->color_selector.elm_selector_window);
959    evas_object_size_hint_weight_set(rect_frame, EVAS_HINT_EXPAND, 0.3);
960    evas_object_size_hint_align_set(rect_frame, EVAS_HINT_FILL, EVAS_HINT_FILL);
961    elm_object_text_set(rect_frame, "Color View");
962    elm_box_pack_end(box, rect_frame);
963    evas_object_show(rect_frame);
964
965    rect = evas_object_rectangle_add(evas_object_evas_get(window->color_selector.elm_selector_window));
966    elm_object_content_set(rect_frame, rect);
967    ewk_color_picker_color_get(window->color_selector.ewk_picker, &r, &g, &b, &a);
968    evas_object_color_set(rect, r, g, b, a);
969    evas_object_show(rect);
970
971    /* Show color selector */
972    cs_frame = elm_frame_add(window->color_selector.elm_selector_window);
973    evas_object_size_hint_weight_set(cs_frame, EVAS_HINT_EXPAND, 0.7);
974    evas_object_size_hint_align_set(cs_frame, EVAS_HINT_FILL, EVAS_HINT_FILL);
975    elm_object_text_set(cs_frame, "Color Selector");
976    elm_box_pack_end(box, cs_frame);
977    evas_object_show(cs_frame);
978
979    window->color_selector.elm_selector = elm_colorselector_add(window->color_selector.elm_selector_window);
980    elm_object_content_set(cs_frame, window->color_selector.elm_selector);
981    evas_object_show(window->color_selector.elm_selector);
982
983    /* OK, Cancel Buttons */
984    button_box = elm_box_add(window->color_selector.elm_selector_window);
985    elm_box_horizontal_set(button_box, EINA_TRUE);
986    evas_object_size_hint_min_set(button_box, 200, 50);
987    elm_box_pack_end(box, button_box);
988    evas_object_show(button_box);
989
990    ok_button = elm_button_add(window->color_selector.elm_selector_window);
991    elm_object_text_set(ok_button, "OK");
992    elm_box_pack_end(button_box, ok_button);
993    evas_object_show(ok_button);
994
995    cancel_button = elm_button_add(window->color_selector.elm_selector_window);
996    elm_object_text_set(cancel_button, "Cancel");
997    elm_box_pack_end(button_box, cancel_button);
998    evas_object_show(cancel_button);
999
1000    evas_object_smart_callback_add(ok_button, "clicked", _color_picker_ok_clicked_cb, &(window->color_selector));
1001    evas_object_smart_callback_add(cancel_button, "clicked", _color_picker_cancel_clicked_cb,
1002      window->color_selector.ewk_picker);
1003    evas_object_smart_callback_add(window->color_selector.elm_selector_window, "delete,request",
1004      _color_picker_cancel_clicked_cb, window->color_selector.ewk_picker);
1005    evas_object_smart_callback_add(window->color_selector.elm_selector, "changed", _color_changed_cb, rect);
1006    evas_object_smart_callback_add(window->color_selector.elm_selector, "color,item,selected", _color_item_selected_cb,
1007      rect);
1008
1009    int x, y, width, height;
1010    evas_object_geometry_get(window->elm_window, &x, &y, &width, &height);
1011
1012    elm_win_center(window->color_selector.elm_selector_window, EINA_TRUE, EINA_TRUE);
1013    evas_object_resize(window->color_selector.elm_selector_window, 350, 500);
1014    evas_object_show(window->color_selector.elm_selector_window);
1015
1016    return EINA_TRUE;
1017 }
1018
1019 static int
1020 quit(Eina_Bool success, const char *msg)
1021 {
1022    if (msg)
1023      success ? INFO("%s", msg) : ERROR("%s", msg);
1024
1025    eina_log_domain_unregister(_log_domain_id);
1026    ewk_object_unref(configuration());
1027    ewk_shutdown();
1028    elm_shutdown();
1029
1030    if (!success)
1031      return EXIT_FAILURE;
1032
1033    return EXIT_SUCCESS;
1034 }
1035
1036 static Eina_Bool
1037 has_scheme(const char *url)
1038 {
1039    return !!strstr(url, "://");
1040 }
1041
1042 static char *
1043 url_from_user_input(const char *arg)
1044 {
1045    /* If it is already a URL, return the argument as is. */
1046    if (has_scheme(arg) || eina_str_has_prefix(arg, JAVASCRIPT_SCHEME) || !strcasecmp(arg, "about:blank"))
1047      return strdup(arg);
1048
1049    Eina_Strbuf *buf = eina_strbuf_manage_new(eina_file_path_sanitize(arg));
1050
1051    /* Check if the path exists. */
1052    if (ecore_file_exists(eina_strbuf_string_get(buf))) {
1053      /* File exists, convert local path to a URL. */
1054      eina_strbuf_prepend(buf, FILE_SCHEME);
1055    } else {
1056      /* The path does not exist, convert it to a URL by
1057         prepending http:// scheme:
1058         www.google.com -> http://www.google.com */
1059      eina_strbuf_string_free(buf);
1060      eina_strbuf_append_printf(buf, "%s%s", HTTP_SCHEME, arg);
1061    }
1062    char *url = eina_strbuf_string_steal(buf);
1063    eina_strbuf_free(buf);
1064
1065    return url;
1066 }
1067
1068 static Eina_Bool
1069 url_load_from_user_input(Evas_Object *ewk_view, const char *url)
1070 {
1071    if (!ewk_view || !url)
1072      return EINA_FALSE;
1073
1074    if (eina_str_has_prefix(url, JAVASCRIPT_SCHEME))
1075      return ewk_view_script_execute(ewk_view, strstr(url, JAVASCRIPT_SCHEME), 0, 0);
1076
1077    return ewk_view_url_set(ewk_view, url);
1078 }
1079
1080 static void
1081 _url_bar_activated_cb(void *user_data, Evas_Object *url_bar, void *event_info)
1082 {
1083    Browser_Window *window = (Browser_Window *)user_data;
1084
1085    const char *markup_url = elm_entry_entry_get(url_bar);
1086    char *user_url = elm_entry_markup_to_utf8(markup_url);
1087    char *url = url_from_user_input(user_url);
1088    url_load_from_user_input(window->ewk_view, url);
1089
1090    free(user_url);
1091    free(url);
1092
1093    /* Give focus back to the view */
1094    view_focus_set(window, EINA_TRUE);
1095 }
1096
1097 static void
1098 _url_bar_clicked_cb(void *user_data, Evas_Object *url_bar, void *event_info)
1099 {
1100    Browser_Window *window = (Browser_Window *)user_data;
1101
1102    /* Grab focus from the view */
1103    evas_object_focus_set(window->ewk_view, EINA_FALSE);
1104    elm_object_focus_set(url_bar, EINA_TRUE);
1105 }
1106
1107 static void
1108 _search_field_aborted_cb(void *user_data, Evas_Object *search_field, void *event_info)
1109 {
1110    Browser_Window *window = (Browser_Window *)user_data;
1111    search_box_hide(window);
1112
1113    /* Give focus back to the view */
1114    view_focus_set(window, EINA_TRUE);
1115 }
1116
1117 static void
1118 _search_field_activated_cb(void *user_data, Evas_Object *search_field, void *event_info)
1119 {
1120    Browser_Window *window = (Browser_Window *)user_data;
1121
1122    const char *markup_text = elm_entry_entry_get(search_field);
1123    char *text = elm_entry_markup_to_utf8(markup_text);
1124    ewk_view_text_find(window->ewk_view, text, search_flags, MAX_SEARCH_COUNT);
1125    free(text);
1126
1127    /* Grab focus from the view */
1128    evas_object_focus_set(window->ewk_view, EINA_FALSE);
1129    elm_object_focus_set(search_field, EINA_TRUE);
1130 }
1131
1132 static void
1133 _search_field_clicked_cb(void *user_data, Evas_Object *search_field, void *event_info)
1134 {
1135    Browser_Window *window = (Browser_Window *)user_data;
1136
1137    /* Grab focus from the view */
1138    evas_object_focus_set(window->ewk_view, EINA_FALSE);
1139    elm_object_focus_set(search_field, EINA_TRUE);
1140 }
1141
1142 static void
1143 _back_button_clicked_cb(void *user_data, Evas_Object *back_button, void *event_info)
1144 {
1145    if (longpress_enabled)
1146      return;
1147
1148    Browser_Window *window = (Browser_Window *)user_data;
1149
1150    ewk_view_back(window->ewk_view);
1151    /* Update back button state */
1152    elm_object_disabled_set(back_button, !ewk_view_back_possible(window->ewk_view));
1153 }
1154
1155 static void
1156 _forward_button_clicked_cb(void *user_data, Evas_Object *forward_button, void *event_info)
1157 {
1158    if (longpress_enabled)
1159      return;
1160
1161    Browser_Window *window = (Browser_Window *)user_data;
1162
1163    ewk_view_forward(window->ewk_view);
1164    /* Update forward button state */
1165    elm_object_disabled_set(forward_button, !ewk_view_forward_possible(window->ewk_view));
1166 }
1167
1168 static void
1169 _search_backward_button_clicked_cb(void *user_data, Evas_Object *search_backward_button, void *event_info)
1170 {
1171    Browser_Window *window = (Browser_Window *)user_data;
1172
1173    char *text = elm_entry_markup_to_utf8(elm_entry_entry_get(window->search.search_field));
1174    ewk_view_text_find(window->ewk_view, text, search_flags | EWK_FIND_OPTIONS_BACKWARDS, MAX_SEARCH_COUNT);
1175    free(text);
1176 }
1177
1178 static void
1179 _search_forward_button_clicked_cb(void *user_data, Evas_Object *search_forward_button, void *event_info)
1180 {
1181    Browser_Window *window = (Browser_Window *)user_data;
1182
1183    char *text = elm_entry_markup_to_utf8(elm_entry_entry_get(window->search.search_field));
1184    ewk_view_text_find(window->ewk_view, text, search_flags, MAX_SEARCH_COUNT);
1185    free(text);
1186 }
1187
1188 static void
1189 _search_case_option_changed(void *user_data, Evas_Object *search_case_check_box, void *event_info)
1190 {
1191    Browser_Window *window = (Browser_Window *)user_data;
1192    char *text = elm_entry_markup_to_utf8(elm_entry_entry_get(window->search.search_field));
1193
1194    /* Bit toggle the case sensitive flag */
1195    search_flags = search_flags ^ EWK_FIND_OPTIONS_CASE_INSENSITIVE;
1196
1197    ewk_view_text_find(window->ewk_view, text, search_flags, MAX_SEARCH_COUNT);
1198    free(text);
1199 }
1200
1201 static void
1202 _search_word_start_option_changed_cb(void *user_data, Evas_Object *search_word_start_check_box, void *event_info)
1203 {
1204    Browser_Window *window = (Browser_Window *)user_data;
1205    char *text = elm_entry_markup_to_utf8(elm_entry_entry_get(window->search.search_field));
1206
1207    /* Bit toggle the word start flag */
1208    search_flags = search_flags ^ EWK_FIND_OPTIONS_AT_WORD_STARTS;
1209
1210    ewk_view_text_find(window->ewk_view, text, search_flags, MAX_SEARCH_COUNT);
1211    free(text);
1212 }
1213
1214 static void
1215 _search_close_button_clicked_cb(void *user_data, Evas_Object *search_close_button, void *event_info)
1216 {
1217    Browser_Window *window = (Browser_Window *)user_data;
1218
1219    search_box_hide(window);
1220 }
1221
1222 static void
1223 _refresh_button_clicked_cb(void *user_data, Evas_Object *refresh_button, void *event_info)
1224 {
1225    Browser_Window *window = (Browser_Window *)user_data;
1226
1227    Evas *evas = evas_object_evas_get(refresh_button);
1228    Eina_Bool ctrlPressed = evas_key_modifier_is_set(evas_key_modifier_get(evas), "Control");
1229    if (ctrlPressed) {
1230      INFO("Reloading and bypassing cache...");
1231      ewk_view_reload_bypass_cache(window->ewk_view);
1232    } else {
1233      INFO("Reloading...");
1234      ewk_view_reload(window->ewk_view);
1235    }
1236 }
1237
1238 static void
1239 _stop_button_clicked_cb(void *user_data, Evas_Object *stop_button, void *event_info)
1240 {
1241    Browser_Window *window = (Browser_Window *)user_data;
1242
1243    INFO("Stop was Pressed. Aborting load...");
1244    ewk_view_stop(window->ewk_view);
1245 }
1246
1247 static char *
1248 list_item_label_get(void *data, Evas_Object *obj, const char *part)
1249 {
1250    int len = strlen((char *)data);
1251    char *buf = (char *)malloc(sizeof(char) * (len + 1));
1252    snprintf(buf, len + 1, "%s", (char *)data);
1253    return buf;
1254 }
1255
1256 static void
1257 _list_item_select_cb(void *user_data, Evas_Object *obj, void *event_info)
1258 {
1259    Browser_Window *window = evas_object_data_get(obj, "Browser_Window");
1260    ewk_view_navigate_to(window->ewk_view, user_data);
1261    history_list_hide(window);
1262    evas_object_data_del(obj, "Browser_Window");
1263 }
1264
1265 static void
1266 navigation_button_longpress_process(void *user_data, Eina_Bool forward_navigation_enabled)
1267 {
1268    if (longpress_enabled)
1269      return;
1270
1271    longpress_enabled = EINA_TRUE;
1272    Browser_Window *window = (Browser_Window *)user_data;
1273
1274    Ewk_Back_Forward_List *list = ewk_view_back_forward_list_get(window->ewk_view);
1275    const Eina_List *l;
1276    void *data;
1277    static Elm_Genlist_Item_Class *list_item = NULL;
1278    const char *title = NULL;
1279    int item_count;
1280    int x;
1281    int y;
1282    int width;
1283    int height;
1284    size_t index;
1285
1286    evas_object_data_set(window->history.history_list, "Browser_Window", window);
1287
1288    if (forward_navigation_enabled)
1289      window->history.history_list_items = ewk_back_forward_list_forward_items_copy(list);
1290    else
1291      window->history.history_list_items = ewk_back_forward_list_back_items_copy(list);
1292
1293    if (!list_item) {
1294      list_item = elm_genlist_item_class_new();
1295      list_item->item_style = "default";
1296      list_item->func.text_get = list_item_label_get;
1297      list_item->func.content_get = NULL;
1298      list_item->func.state_get = NULL;
1299      list_item->func.del = NULL;
1300    }
1301
1302    item_count = eina_list_count(window->history.history_list_items);
1303    INFO("navigation_button_longpress_process : Item count = %d forward_navigation_enabled = %d", item_count, forward_navigation_enabled);
1304
1305    EINA_LIST_FOREACH(window->history.history_list_items, l, data) {
1306      title = ewk_back_forward_list_item_title_get(data);
1307      INFO(" title = %s", title);
1308      elm_genlist_item_append(window->history.history_list, list_item, (void *)(title), NULL, ELM_GENLIST_ITEM_NONE, _list_item_select_cb, data);
1309    }
1310
1311    if (item_count > 0) {
1312      evas_object_geometry_get(window->elm_window, &x, &y, &width, &height);
1313      elm_list_go(window->history.history_list);
1314      evas_object_resize(window->history.history_box , width / 3 , LIST_ITEM_HEIGHT * item_count);
1315
1316      if (forward_navigation_enabled) {
1317        evas_object_move(window->history.history_box , x + TOOL_BAR_BUTTON_SIZE + 1, y + TOOL_BAR_BUTTON_SIZE);
1318        evas_object_move(window->history.history_list , x + TOOL_BAR_BUTTON_SIZE + 1, y + TOOL_BAR_BUTTON_SIZE);
1319      } else {
1320        evas_object_move(window->history.history_box , x, y + TOOL_BAR_BUTTON_SIZE);
1321        evas_object_move(window->history.history_list , x, y + TOOL_BAR_BUTTON_SIZE);
1322      }
1323
1324      elm_genlist_mode_set(window->history.history_list, ELM_LIST_COMPRESS);
1325      evas_object_show(window->history.history_box);
1326      evas_object_show(window->history.history_list);
1327      evas_object_focus_set(window->ewk_view, EINA_FALSE);
1328      elm_object_focus_set(window->history.history_list, EINA_TRUE);
1329    } else
1330      longpress_enabled = EINA_FALSE;
1331 }
1332
1333 static void
1334 _forward_button_longpress_cb(void *user_data, Evas_Object *forward_button, void *event_info)
1335 {
1336    Browser_Window *window = (Browser_Window *)user_data;
1337
1338    navigation_button_longpress_process(user_data, EINA_TRUE);
1339    elm_object_disabled_set(forward_button, !ewk_view_back_possible(window->ewk_view));
1340 }
1341
1342 static void
1343 _back_button_longpress_cb(void *user_data, Evas_Object *back_button, void *event_info)
1344 {
1345    Browser_Window *window = (Browser_Window *)user_data;
1346
1347    navigation_button_longpress_process(user_data, EINA_FALSE);
1348    elm_object_disabled_set(back_button, !ewk_view_back_possible(window->ewk_view));
1349 }
1350
1351 static void
1352 _ok_clicked_cb(void *user_data, Evas_Object *obj, void *event_info)
1353 {
1354    Eina_Bool *confirmed = (Eina_Bool *)user_data;
1355    *confirmed = EINA_TRUE;
1356 }
1357
1358 static Eina_Stringshare *
1359 _file_entry_dialog_show(Browser_Window *window, const char *label_tag, const char *default_text)
1360 {
1361    Evas_Object *file_popup = elm_popup_add(window->elm_window);
1362    evas_object_size_hint_weight_set(file_popup, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
1363    evas_object_show(file_popup);
1364
1365    Evas_Object *vbox = elm_box_add(file_popup);
1366    evas_object_size_hint_weight_set(vbox, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
1367    evas_object_size_hint_align_set(vbox, EVAS_HINT_FILL, EVAS_HINT_FILL);
1368    elm_object_content_set(file_popup, vbox);
1369    evas_object_show(vbox);
1370
1371    Evas_Object *label = elm_label_add(window->elm_window);
1372    elm_object_text_set(label, label_tag);
1373    evas_object_size_hint_weight_set(label, EVAS_HINT_EXPAND, 0.0);
1374    evas_object_size_hint_align_set(label, EVAS_HINT_FILL, 0.5);
1375    evas_object_color_set(label, 23, 45, 67, 142);
1376    elm_box_pack_end(vbox, label);
1377    evas_object_show(label);
1378
1379    Evas_Object *fs_entry = elm_fileselector_entry_add(file_popup);
1380    elm_fileselector_is_save_set(fs_entry, EINA_TRUE);
1381    evas_object_size_hint_align_set(fs_entry, EVAS_HINT_FILL, 0);
1382    elm_fileselector_path_set(fs_entry, default_text);
1383    elm_object_text_set(fs_entry, "FileChooser");
1384    elm_box_pack_end(vbox, fs_entry);
1385    evas_object_show(fs_entry);
1386
1387    Evas_Object *hbox = elm_box_add(file_popup);
1388    evas_object_size_hint_weight_set(hbox, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
1389    elm_box_horizontal_set(hbox, EINA_TRUE);
1390    evas_object_size_hint_align_set(hbox, EVAS_HINT_FILL, EVAS_HINT_FILL);
1391    elm_box_pack_end(vbox, hbox);
1392    evas_object_show(hbox);
1393
1394    Eina_Bool ok = EINA_FALSE;
1395    Evas_Object *ok_button = elm_button_add(file_popup);
1396    elm_object_text_set(ok_button, "OK");
1397    evas_object_smart_callback_add(ok_button, "clicked", _ok_clicked_cb, &ok);
1398    elm_box_pack_end(hbox, ok_button);
1399    evas_object_show(ok_button);
1400
1401    Eina_Bool cancel = EINA_FALSE;
1402    Evas_Object *cancel_button = elm_button_add(file_popup);
1403    elm_object_text_set(cancel_button, "Cancel");
1404    evas_object_smart_callback_add(cancel_button, "clicked", _ok_clicked_cb, &cancel);
1405    elm_box_pack_end(hbox, cancel_button);
1406    evas_object_show(cancel_button);
1407
1408    while (ok != EINA_TRUE && cancel != EINA_TRUE)
1409     ecore_main_loop_iterate();
1410
1411    Eina_Stringshare *file_path = ok ? eina_stringshare_add(elm_fileselector_path_get(fs_entry)) : NULL;
1412    evas_object_del(file_popup);
1413    return file_path;
1414 }
1415
1416 static void
1417 _javascript_alert_cb(Ewk_View_Smart_Data *smartData, const char *message)
1418 {
1419    Browser_Window *window = window_find_with_ewk_view(smartData->self);
1420
1421    Evas_Object *alert_popup = elm_popup_add(window->elm_window);
1422    evas_object_size_hint_weight_set(alert_popup, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
1423    elm_object_text_set(alert_popup, message);
1424    elm_object_part_text_set(alert_popup, "title,text", "Alert");
1425
1426    /* Popup buttons */
1427    Eina_Bool ok = EINA_FALSE;
1428    Evas_Object *button = elm_button_add(alert_popup);
1429    elm_object_text_set(button, "OK");
1430    elm_object_part_content_set(alert_popup, "button1", button);
1431    evas_object_smart_callback_add(button, "clicked", _ok_clicked_cb, &ok);
1432    elm_object_focus_set(button, EINA_TRUE);
1433    evas_object_show(alert_popup);
1434
1435    while (ok != EINA_TRUE)
1436       ecore_main_loop_iterate();
1437
1438    evas_object_del(alert_popup);
1439 }
1440
1441 static Eina_Bool
1442 _javascript_confirm_cb(Ewk_View_Smart_Data *smartData, const char *message)
1443 {
1444    Browser_Window *window = window_find_with_ewk_view(smartData->self);
1445
1446    Evas_Object *confirm_popup = elm_popup_add(window->elm_window);
1447    evas_object_size_hint_weight_set(confirm_popup, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
1448    elm_object_text_set(confirm_popup, message);
1449    elm_object_part_text_set(confirm_popup, "title,text", "Confirmation");
1450
1451    /* Popup buttons */
1452    Eina_Bool cancel = EINA_FALSE;
1453    Evas_Object *cancel_button = elm_button_add(confirm_popup);
1454    elm_object_text_set(cancel_button, "Cancel");
1455    elm_object_part_content_set(confirm_popup, "button1", cancel_button);
1456    evas_object_smart_callback_add(cancel_button, "clicked", _ok_clicked_cb, &cancel);
1457    Evas_Object *ok_button = elm_button_add(confirm_popup);
1458    Eina_Bool ok = EINA_FALSE;
1459    elm_object_text_set(ok_button, "OK");
1460    elm_object_part_content_set(confirm_popup, "button2", ok_button);
1461    evas_object_smart_callback_add(ok_button, "clicked", _ok_clicked_cb, &ok);
1462    elm_object_focus_set(ok_button, EINA_TRUE);
1463    evas_object_show(confirm_popup);
1464
1465    while (cancel != EINA_TRUE && ok != EINA_TRUE)
1466       ecore_main_loop_iterate();
1467
1468    evas_object_del(confirm_popup);
1469
1470    return ok;
1471 }
1472
1473 static const char *
1474 _javascript_prompt_cb(Ewk_View_Smart_Data *smartData, const char *message, const char *default_value)
1475 {
1476    Browser_Window *window = window_find_with_ewk_view(smartData->self);
1477
1478    Evas_Object *prompt_popup = elm_popup_add(window->elm_window);
1479    evas_object_size_hint_weight_set(prompt_popup, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
1480    elm_object_part_text_set(prompt_popup, "title,text", "Prompt");
1481
1482    /* Popup Content */
1483    Evas_Object *box = elm_box_add(window->elm_window);
1484    elm_box_padding_set(box, 0, 4);
1485    evas_object_size_hint_weight_set(box, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
1486    evas_object_size_hint_align_set(box, EVAS_HINT_FILL, EVAS_HINT_FILL);
1487    evas_object_show(box);
1488
1489    Evas_Object *prompt = elm_label_add(window->elm_window);
1490    elm_object_text_set(prompt, message);
1491    evas_object_size_hint_weight_set(prompt, EVAS_HINT_EXPAND, 0.0);
1492    evas_object_size_hint_align_set(prompt, EVAS_HINT_FILL, 0.5);
1493    elm_box_pack_end(box, prompt);
1494    evas_object_show(prompt);
1495
1496    Evas_Object *entry = elm_entry_add(window->elm_window);
1497    elm_entry_scrollable_set(entry, EINA_TRUE);
1498    elm_entry_single_line_set(entry, EINA_TRUE);
1499    elm_entry_text_style_user_push(entry, "DEFAULT='font_size=18'");
1500    elm_entry_entry_set(entry, default_value ? default_value : "");
1501    elm_entry_select_all(entry);
1502    evas_object_size_hint_weight_set(entry, EVAS_HINT_EXPAND, 0.0);
1503    evas_object_size_hint_align_set(entry, EVAS_HINT_FILL, 0.5);
1504    elm_box_pack_end(box, entry);
1505    elm_object_focus_set(entry, EINA_TRUE);
1506    evas_object_show(entry);
1507
1508    elm_object_content_set(prompt_popup, box);
1509
1510    /* Popup buttons */
1511    Eina_Bool cancel = EINA_FALSE;
1512    Evas_Object *cancel_button = elm_button_add(prompt_popup);
1513    elm_object_text_set(cancel_button, "Cancel");
1514    elm_object_part_content_set(prompt_popup, "button1", cancel_button);
1515    evas_object_smart_callback_add(cancel_button, "clicked", _ok_clicked_cb, &cancel);
1516    Eina_Bool ok = EINA_FALSE;
1517    Evas_Object *ok_button = elm_button_add(prompt_popup);
1518    elm_object_text_set(ok_button, "OK");
1519    elm_object_part_content_set(prompt_popup, "button2", ok_button);
1520    evas_object_smart_callback_add(ok_button, "clicked", _ok_clicked_cb, &ok);
1521    evas_object_show(prompt_popup);
1522
1523    while (cancel != EINA_TRUE && ok != EINA_TRUE)
1524       ecore_main_loop_iterate();
1525
1526    /* The return string need to be stringshared */
1527    const char *prompt_text = ok ? eina_stringshare_add(elm_entry_entry_get(entry)) : NULL;
1528    evas_object_del(prompt_popup);
1529
1530    return prompt_text;
1531 }
1532
1533 static Eina_Bool
1534 _javascript_before_unload_confirm_cb(Ewk_View_Smart_Data *smartData, const char *message)
1535 {
1536    return _javascript_confirm_cb(smartData, "Will you leave this page?");
1537 }
1538
1539 static void
1540 _popup_menu_item_clicked_cb(void *user_data, Evas_Object *obj, void *event_info)
1541 {
1542    Browser_Window *window = (Browser_Window *)user_data;
1543    Elm_Object_Item *item = (Elm_Object_Item *)event_info;
1544
1545    INFO("Selected popup menu index: %u", elm_menu_item_index_get(item));
1546    ewk_popup_menu_selected_index_set(window->popup.ewk_menu, elm_menu_item_index_get(item));
1547
1548    // Close popup menu.
1549    ewk_popup_menu_close(window->popup.ewk_menu);
1550 }
1551
1552 static void
1553 popup_menu_populate(Evas_Object *elm_menu, Ewk_Popup_Menu *ewk_menu, void *user_data)
1554 {
1555    const Eina_List* ewk_items = ewk_popup_menu_items_get(ewk_menu);
1556
1557    void *data;
1558    const Eina_List *l;
1559    EINA_LIST_FOREACH(ewk_items, l, data) {
1560      Ewk_Popup_Menu_Item *ewk_item = (Ewk_Popup_Menu_Item *)data;
1561      switch (ewk_popup_menu_item_type_get(ewk_item)) {
1562      case EWK_POPUP_MENU_SEPARATOR:
1563        elm_menu_item_separator_add(elm_menu, NULL);
1564        break;
1565      case EWK_POPUP_MENU_ITEM:
1566        if (ewk_popup_menu_item_is_label_get(ewk_item)) {
1567          Elm_Object_Item *item = elm_menu_item_add(elm_menu, NULL, NULL, ewk_popup_menu_item_text_get(ewk_item), NULL, NULL);
1568          elm_object_item_disabled_set(item, EINA_TRUE);
1569        } else {
1570          Elm_Object_Item *item = elm_menu_item_add(elm_menu, NULL, NULL, ewk_popup_menu_item_text_get(ewk_item), _popup_menu_item_clicked_cb, user_data);
1571          const char *tooltip_text = ewk_popup_menu_item_tooltip_get(ewk_item);
1572          if (tooltip_text && tooltip_text[0] != '\0')
1573            elm_object_item_tooltip_text_set(item, tooltip_text);
1574          elm_object_item_disabled_set(item, !ewk_popup_menu_item_enabled_get(ewk_item));
1575          elm_menu_item_selected_set(item, ewk_popup_menu_item_selected_get(ewk_item));
1576        }
1577        break;
1578      default:
1579        INFO("Unrecognized popup menu item type!");
1580        break;
1581      }
1582    }
1583 }
1584
1585 static Eina_Bool
1586 _popup_menu_show(Ewk_View_Smart_Data *smartData, Eina_Rectangle rect, Ewk_Text_Direction text_direction, double page_scale_factor, Ewk_Popup_Menu *ewk_menu)
1587 {
1588    Browser_Window *window = window_find_with_ewk_view(smartData->self);
1589
1590    if (window->popup.elm_menu)
1591      evas_object_del(window->popup.elm_menu);
1592
1593    window->popup.elm_menu = elm_menu_add(window->elm_window);
1594    window->popup.ewk_menu = ewk_menu;
1595
1596    popup_menu_populate(window->popup.elm_menu, ewk_menu, window);
1597
1598    INFO("Showing popup menu at (%d, %d)", rect.x, rect.y);
1599    elm_menu_move(window->popup.elm_menu, rect.x, rect.y);
1600    evas_object_show(window->popup.elm_menu);
1601
1602    return EINA_TRUE;
1603 }
1604
1605 static Eina_Bool
1606 _popup_menu_hide(Ewk_View_Smart_Data *smartData)
1607 {
1608    Browser_Window *window = window_find_with_ewk_view(smartData->self);
1609
1610    if (!window->popup.elm_menu)
1611      return EINA_FALSE;
1612
1613    elm_menu_close(window->popup.elm_menu);
1614    window->popup.ewk_menu = NULL;
1615
1616    return EINA_TRUE;
1617 }
1618
1619 static Eina_Bool
1620 _window_geometry_get(Ewk_View_Smart_Data *sd, Evas_Coord *x, Evas_Coord *y, Evas_Coord *width, Evas_Coord *height)
1621 {
1622    Browser_Window *window = window_find_with_ewk_view(sd->self);
1623
1624    evas_object_geometry_get(window->elm_window, x, y, width, height);
1625
1626    return EINA_TRUE;
1627 }
1628
1629 static Eina_Bool
1630 _window_geometry_set(Ewk_View_Smart_Data *sd, Evas_Coord x, Evas_Coord y, Evas_Coord width, Evas_Coord height)
1631 {
1632    Browser_Window *window = window_find_with_ewk_view(sd->self);
1633
1634    evas_object_move(window->elm_window, x, y);
1635    evas_object_resize(window->elm_window, width, height);
1636
1637    return EINA_TRUE;
1638 }
1639
1640 typedef struct {
1641    Evas_Object *ewk_view;
1642    Evas_Object *permission_popup;
1643 } PermissionData;
1644
1645 static void
1646 _fullscreen_accept_cb(void *user_data, Evas_Object *obj, void *event_info)
1647 {
1648    PermissionData *permission_data = (PermissionData *)user_data;
1649    Browser_Window *window = window_find_with_ewk_view(permission_data->ewk_view);
1650
1651    elm_win_resize_object_del(window->elm_window, permission_data->permission_popup);
1652    evas_object_del(permission_data->permission_popup);
1653    evas_object_focus_set(permission_data->ewk_view, EINA_TRUE);
1654    free(permission_data);
1655 }
1656
1657 static void
1658 _fullscreen_deny_cb(void *user_data, Evas_Object *obj, void *event_info)
1659 {
1660    PermissionData *permission_data = (PermissionData *)user_data;
1661    Browser_Window *window = window_find_with_ewk_view(permission_data->ewk_view);
1662
1663    ewk_view_fullscreen_exit(permission_data->ewk_view);
1664    elm_win_resize_object_del(window->elm_window, permission_data->permission_popup);
1665    evas_object_del(permission_data->permission_popup);
1666    evas_object_focus_set(permission_data->ewk_view, EINA_TRUE);
1667    free(permission_data);
1668 }
1669
1670 static Eina_Bool
1671 _fullscreen_enter_cb(Ewk_View_Smart_Data *sd, Ewk_Security_Origin *origin)
1672 {
1673    Browser_Window *window = window_find_with_ewk_view(sd->self);
1674
1675    /* Go fullscreen */
1676    toggle_window_fullscreen(window, EINA_TRUE);
1677
1678    /* Show user popup */
1679    Evas_Object *permission_popup = elm_popup_add(window->elm_window);
1680    evas_object_size_hint_weight_set(permission_popup, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
1681
1682    Eina_Strbuf *message = eina_strbuf_new();
1683    eina_strbuf_append_printf(message, "%s is now fullscreen.<br>Press ESC at any time to exit fullscreen.<br>Allow fullscreen?", ewk_security_origin_host_get(origin));
1684    elm_object_text_set(permission_popup, eina_strbuf_string_get(message));
1685    eina_strbuf_free(message);
1686    elm_object_part_text_set(permission_popup, "title,text", "Fullscreen Permission");
1687
1688    /* Popup buttons */
1689    PermissionData *permission_data = (PermissionData *)malloc(sizeof(PermissionData));
1690    permission_data->ewk_view = window->ewk_view;
1691    permission_data->permission_popup = permission_popup;
1692    Evas_Object *accept_button = elm_button_add(permission_popup);
1693    elm_object_text_set(accept_button, "Accept");
1694    elm_object_part_content_set(permission_popup, "button1", accept_button);
1695    evas_object_smart_callback_add(accept_button, "clicked", _fullscreen_accept_cb, permission_data);
1696
1697    Evas_Object *deny_button = elm_button_add(permission_popup);
1698    elm_object_text_set(deny_button, "Deny");
1699    elm_object_part_content_set(permission_popup, "button2", deny_button);
1700    evas_object_smart_callback_add(deny_button, "clicked", _fullscreen_deny_cb, permission_data);
1701    elm_win_resize_object_add(window->elm_window, permission_popup);
1702    evas_object_show(permission_popup);
1703
1704    return EINA_TRUE;
1705 }
1706
1707 static Eina_Bool _fullscreen_exit_cb(Ewk_View_Smart_Data *sd)
1708 {
1709    Browser_Window *window = window_find_with_ewk_view(sd->self);
1710
1711    toggle_window_fullscreen(window, EINA_FALSE);
1712
1713    return EINA_TRUE;
1714 }
1715
1716 static Evas_Object *
1717 _window_create_cb(Ewk_View_Smart_Data *smartData, Ewk_View_Configuration* configuration, const Ewk_Window_Features *window_features)
1718 {
1719    int x = 0;
1720    int y = 0;
1721    int width = 0;
1722    int height = 0;
1723
1724    ewk_window_features_geometry_get(window_features, &x, &y, &width, &height);
1725
1726    if (!width)
1727      width = window_width;
1728
1729    if (!height)
1730      height = window_height;
1731
1732    Browser_Window *window = window_create(configuration, width, height);
1733    Evas_Object *new_view = window->ewk_view;
1734
1735    windows = eina_list_append(windows, window);
1736
1737    INFO("minibrowser: location(%d,%d) size=(%d,%d)", x, y, width, height);
1738
1739    return new_view;
1740 }
1741
1742 static void
1743 _window_close_cb(Ewk_View_Smart_Data *smartData)
1744 {
1745    Browser_Window *window = window_find_with_ewk_view(smartData->self);
1746    window_close(window);
1747 }
1748
1749 static void
1750 _context_menu_item_selected_cb(void *data, Evas_Object *obj, void *event_info)
1751 {
1752    if (!data) {
1753      ERROR("Context menu callback data is NULL.");
1754      return;
1755    }
1756
1757    Ewk_Context_Menu_Item *ewk_item = (Ewk_Context_Menu_Item *)data;
1758    INFO("Selected context menu item: %s.", ewk_context_menu_item_title_get(ewk_item));
1759    ewk_context_menu_item_select(ewk_context_menu_item_parent_menu_get(ewk_item), ewk_item);
1760    ewk_context_menu_hide(ewk_context_menu_item_parent_menu_get(ewk_item));
1761 }
1762
1763 static void
1764 context_menu_populate(Evas_Object* context_menu, Ewk_Context_Menu *ewk_menu, Elm_Object_Item *parent_item)
1765 {
1766    if (!context_menu || !ewk_menu) {
1767      ERROR("Necessary objects are NULL.");
1768      return;
1769    }
1770
1771    const Eina_List *list = ewk_context_menu_items_get(ewk_menu);
1772    const Eina_List *l;
1773    void *data;
1774
1775    Ewk_Context_Menu_Item *ewk_item;
1776    Elm_Object_Item *elm_menu_item;
1777    Evas_Object *elm_check_item;
1778
1779    EINA_LIST_FOREACH(list, l, data) {
1780      ewk_item = (Ewk_Context_Menu_Item *)data;
1781      switch (ewk_context_menu_item_type_get(ewk_item)) {
1782      case EWK_ACTION_TYPE:
1783        elm_menu_item = elm_menu_item_add(context_menu, parent_item, NULL, ewk_context_menu_item_title_get(ewk_item), _context_menu_item_selected_cb, ewk_item);
1784        break;
1785      case EWK_CHECKABLE_ACTION_TYPE:
1786        elm_check_item = elm_check_add(context_menu);
1787        elm_menu_item = elm_menu_item_add(context_menu, parent_item, NULL, ewk_context_menu_item_title_get(ewk_item), _context_menu_item_selected_cb, ewk_item);
1788        elm_object_item_content_set(elm_menu_item, elm_check_item);
1789        elm_check_state_set(elm_check_item, ewk_context_menu_item_checked_get(ewk_item));
1790        break;
1791      case EWK_SUBMENU_TYPE:
1792        elm_menu_item = elm_menu_item_add(context_menu, parent_item, NULL, ewk_context_menu_item_title_get(ewk_item), NULL, ewk_item);
1793        if (elm_menu_item)
1794          context_menu_populate(context_menu, ewk_context_menu_item_submenu_get(ewk_item), elm_menu_item);
1795        break;
1796      default:
1797        continue;
1798      }
1799      elm_object_item_disabled_set(elm_menu_item, !ewk_context_menu_item_enabled_get(ewk_item));
1800    }
1801 }
1802
1803 static Eina_Bool
1804 _context_menu_show(Ewk_View_Smart_Data *sd, Evas_Coord x, Evas_Coord y, Ewk_Context_Menu *menu)
1805 {
1806    Browser_Window *window = window_find_with_ewk_view(sd->self);
1807
1808    if (!window || !menu) {
1809      ERROR("Necessary objects are NULL.");
1810      return EINA_FALSE;
1811    }
1812
1813    window->context_menu.elm_menu = elm_menu_add(window->elm_window);
1814
1815    if (!window->context_menu.elm_menu) {
1816      ERROR("Could not create menu widget.");
1817      return EINA_FALSE;
1818    }
1819
1820    window->context_menu.ewk_menu = menu;
1821
1822    context_menu_populate(window->context_menu.elm_menu, menu, NULL);
1823
1824    INFO("Showing context menu at (%d, %d).", x, y);
1825    elm_menu_move(window->context_menu.elm_menu, x, y);
1826    evas_object_show(window->context_menu.elm_menu);
1827
1828    return EINA_TRUE;
1829 }
1830
1831 static Eina_Bool
1832 _context_menu_hide(Ewk_View_Smart_Data *sd)
1833 {
1834    Browser_Window *window = window_find_with_ewk_view(sd->self);
1835
1836    if (!window || !window->context_menu.elm_menu) {
1837      ERROR("Necessary objects are NULL.");
1838      return EINA_FALSE;
1839    }
1840
1841    elm_menu_close(window->context_menu.elm_menu);
1842    evas_object_del(window->context_menu.elm_menu);
1843    window->context_menu.elm_menu = NULL;
1844    window->context_menu.ewk_menu = NULL;
1845
1846    return EINA_TRUE;
1847 }
1848
1849 static void
1850 auth_popup_close(Auth_Data *auth_data)
1851 {
1852    ewk_object_unref(auth_data->request);
1853    evas_object_del(auth_data->popup);
1854    free(auth_data);
1855 }
1856
1857 static void
1858 _auth_cancel_cb(void *user_data, Evas_Object *obj, void *event_info)
1859 {
1860    Auth_Data *auth_data = (Auth_Data *)user_data;
1861
1862    ewk_auth_request_cancel(auth_data->request);
1863
1864    auth_popup_close(auth_data);
1865 }
1866
1867 static void
1868 _auth_ok_cb(void *user_data, Evas_Object *obj, void *event_info)
1869 {
1870    Auth_Data *auth_data = (Auth_Data *)user_data;
1871
1872    const char *username = elm_entry_entry_get(auth_data->username_entry);
1873    const char *password = elm_entry_entry_get(auth_data->password_entry);
1874    ewk_auth_request_authenticate(auth_data->request, username, password);
1875
1876    auth_popup_close(auth_data);
1877 }
1878
1879 static void
1880 _authentication_request_cb(void *user_data, Evas_Object *obj, void *event_info)
1881 {
1882    Browser_Window *window = (Browser_Window *)user_data;
1883    Ewk_Auth_Request *request = ewk_object_ref((Ewk_Auth_Request *)event_info);
1884
1885    Auth_Data *auth_data = (Auth_Data *)malloc(sizeof(Auth_Data));
1886    auth_data->request = request;
1887
1888    Evas_Object *auth_popup = elm_popup_add(window->elm_window);
1889    auth_data->popup = auth_popup;
1890    evas_object_size_hint_weight_set(auth_popup, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
1891    elm_object_part_text_set(auth_popup, "title,text", "Authentication Required");
1892
1893    /* Popup Content */
1894    Evas_Object *vbox = elm_box_add(auth_popup);
1895    elm_box_padding_set(vbox, 0, 4);
1896    evas_object_size_hint_weight_set(vbox, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
1897    evas_object_size_hint_align_set(vbox, EVAS_HINT_FILL, EVAS_HINT_FILL);
1898    elm_object_content_set(auth_popup, vbox);
1899    evas_object_show(vbox);
1900
1901    /* Authentication message */
1902    Evas_Object *label = elm_label_add(auth_popup);
1903    elm_label_line_wrap_set(label, ELM_WRAP_WORD);
1904    Eina_Strbuf *auth_text = eina_strbuf_new();
1905    const char *host = ewk_auth_request_host_get(request);
1906    const char *realm = ewk_auth_request_realm_get(request);
1907    eina_strbuf_append_printf(auth_text, "A username and password are being requested by %s. The site says: \"%s\"", host, realm ? realm : "");
1908    elm_object_text_set(label, eina_strbuf_string_get(auth_text));
1909    eina_strbuf_free(auth_text);
1910    evas_object_size_hint_weight_set(label, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
1911    evas_object_size_hint_align_set(label, EVAS_HINT_FILL, EVAS_HINT_FILL);
1912    elm_box_pack_end(vbox, label);
1913    evas_object_show(label);
1914
1915    /* Credential table */
1916    Evas_Object *table = elm_table_add(auth_popup);
1917    elm_table_padding_set(table, 2, 2);
1918    elm_table_homogeneous_set(table, EINA_TRUE);
1919    evas_object_size_hint_weight_set(table, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
1920    evas_object_size_hint_align_set(table, EVAS_HINT_FILL, EVAS_HINT_FILL);
1921    elm_box_pack_end(vbox, table);
1922    evas_object_show(table);
1923
1924    /* Username row */
1925    Evas_Object *username_label = elm_label_add(auth_popup);
1926    elm_object_text_set(username_label, "Username:");
1927    evas_object_size_hint_weight_set(username_label, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
1928    evas_object_size_hint_align_set(username_label, 1, EVAS_HINT_FILL);
1929    elm_table_pack(table, username_label, 0, 0, 1, 1);
1930    evas_object_show(username_label);
1931
1932    Evas_Object *username_entry = elm_entry_add(auth_popup);
1933    auth_data->username_entry = username_entry;
1934    elm_entry_scrollable_set(username_entry, EINA_TRUE);
1935    elm_entry_single_line_set(username_entry, EINA_TRUE);
1936    elm_entry_text_style_user_push(username_entry, "DEFAULT='font_size=18'");
1937    const char *suggested_username = ewk_auth_request_suggested_username_get(request);
1938    elm_entry_entry_set(username_entry, suggested_username ? suggested_username : "");
1939    evas_object_size_hint_weight_set(username_entry, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
1940    evas_object_size_hint_align_set(username_entry, EVAS_HINT_FILL, EVAS_HINT_FILL);
1941    elm_table_pack(table, username_entry, 1, 0, 2, 1);
1942    elm_object_focus_set(username_entry, EINA_TRUE);
1943    evas_object_show(username_entry);
1944
1945    /* Password row */
1946    Evas_Object *password_label = elm_label_add(auth_popup);
1947    elm_object_text_set(password_label, "Password:");
1948    evas_object_size_hint_weight_set(password_label, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
1949    evas_object_size_hint_align_set(password_label, 1, EVAS_HINT_FILL);
1950    elm_table_pack(table, password_label, 0, 1, 1, 1);
1951    evas_object_show(password_label);
1952
1953    Evas_Object *password_entry = elm_entry_add(auth_popup);
1954    auth_data->password_entry = password_entry;
1955    elm_entry_scrollable_set(password_entry, EINA_TRUE);
1956    elm_entry_single_line_set(password_entry, EINA_TRUE);
1957    elm_entry_password_set(password_entry, EINA_TRUE);
1958    elm_entry_text_style_user_push(password_entry, "DEFAULT='font_size=18'");
1959    evas_object_size_hint_weight_set(password_entry, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
1960    evas_object_size_hint_align_set(password_entry, EVAS_HINT_FILL, EVAS_HINT_FILL);
1961    elm_table_pack(table, password_entry, 1, 1, 2, 1);
1962    evas_object_show(password_entry);
1963
1964    /* Popup buttons */
1965    Evas_Object *cancel_button = elm_button_add(auth_popup);
1966    elm_object_text_set(cancel_button, "Cancel");
1967    elm_object_part_content_set(auth_popup, "button1", cancel_button);
1968    evas_object_smart_callback_add(cancel_button, "clicked", _auth_cancel_cb, auth_data);
1969    Evas_Object *ok_button = elm_button_add(auth_popup);
1970    elm_object_text_set(ok_button, "OK");
1971    elm_object_part_content_set(auth_popup, "button2", ok_button);
1972    evas_object_smart_callback_add(ok_button, "clicked", _auth_ok_cb, auth_data);
1973    evas_object_show(auth_popup);
1974 }
1975
1976 static void
1977 _search_text_found_cb(void *user_data, Evas_Object *obj, void *event_info)
1978 {
1979    Browser_Window *window = (Browser_Window *)user_data;
1980
1981    const int *match_count = (const int *)(event_info);
1982
1983    if (*match_count) {
1984      Eina_Strbuf *search_text = eina_strbuf_new();
1985      eina_strbuf_append_printf(search_text, "  %d  Matches Found " , *match_count);
1986      elm_object_text_set(window->search.search_field_count, eina_strbuf_string_get(search_text));
1987      eina_strbuf_free(search_text);
1988    } else
1989      elm_object_text_set(window->search.search_field_count, " No Matches Found");
1990
1991    evas_object_focus_set(window->ewk_view, EINA_FALSE);
1992    elm_object_focus_set(window->search.search_field_count, EINA_FALSE);
1993    elm_object_focus_set(window->search.search_field, EINA_TRUE);
1994 }
1995
1996 static void
1997 _tooltip_text_set(void *user_data, Evas_Object *obj, void *event_info)
1998 {
1999    Browser_Window *window = (Browser_Window *)user_data;
2000    const char *message = (const char*)event_info;
2001
2002    elm_object_tooltip_text_set(window->elm_window, message);
2003    window->tooltip.text_set = EINA_TRUE;
2004    window_tooltip_update(window);
2005 }
2006
2007 static void
2008 _tooltip_text_unset(void *user_data, Evas_Object *obj, void *event_info)
2009 {
2010    Browser_Window *window = (Browser_Window *)user_data;
2011
2012    window_tooltip_hide(window);
2013    elm_object_tooltip_unset(window->elm_window);
2014    window->tooltip.text_set = EINA_FALSE;
2015 }
2016
2017 static void
2018 _navigation_policy_decision_cb(void *user_data, Evas_Object *obj, void *event_info)
2019 {
2020    Ewk_Navigation_Policy_Decision *decision = (Ewk_Navigation_Policy_Decision *)event_info;
2021
2022    if (ewk_navigation_policy_mouse_button_get(decision) == EWK_EVENT_MOUSE_BUTTON_MIDDLE) {
2023      Browser_Window *window = window_create(NULL, 0, 0);
2024      ewk_view_url_set(window->ewk_view, ewk_url_request_url_get(ewk_navigation_policy_request_get(decision)));
2025      windows = eina_list_append(windows, window);
2026      INFO("Mouse middle button pressed, open link in new window");
2027
2028      ewk_navigation_policy_decision_reject(decision);
2029    }
2030 }
2031
2032 static void
2033 _search_button_clicked_cb(void *user_data, Evas_Object *home_button, void *event_info)
2034 {
2035    Browser_Window *window = (Browser_Window *)user_data;
2036
2037    search_box_show(window);
2038 }
2039
2040 static void
2041 _home_button_clicked_cb(void *user_data, Evas_Object *home_button, void *event_info)
2042 {
2043    Browser_Window *window = (Browser_Window *)user_data;
2044
2045    ewk_view_url_set(window->ewk_view, DEFAULT_URL);
2046 }
2047
2048 static void
2049 _window_deletion_cb(void *user_data, Evas_Object *elm_window, void *event_info)
2050 {
2051    Browser_Window *window = (Browser_Window *)user_data;
2052    ewk_view_try_close(window->ewk_view);
2053 }
2054
2055 static Evas_Object *
2056 _create_toolbar_button(Evas_Object *elm_window, const char *icon_name)
2057 {
2058    Evas_Object *button = elm_button_add(elm_window);
2059
2060    Evas_Object *icon = elm_icon_add(elm_window);
2061    elm_icon_standard_set(icon, icon_name);
2062    evas_object_size_hint_max_set(icon, TOOL_BAR_ICON_SIZE, TOOL_BAR_ICON_SIZE);
2063    evas_object_color_set(icon, 0, 255, 255, 255);
2064    evas_object_show(icon);
2065    elm_object_part_content_set(button, "icon", icon);
2066    evas_object_size_hint_min_set(button, TOOL_BAR_BUTTON_SIZE, TOOL_BAR_BUTTON_SIZE);
2067
2068    return button;
2069 }
2070
2071 static Browser_Window *window_create(Ewk_View_Configuration* configuration, int width, int height)
2072 {
2073    Browser_Window *window = calloc(1, sizeof(Browser_Window));
2074    if (!window) {
2075      ERROR("Could not create browser window.");
2076      return NULL;
2077    }
2078
2079    /* Initialize tooltip information */
2080    window->tooltip.show_timer = NULL;
2081    window->tooltip.activated = EINA_FALSE;
2082    window->tooltip.text_set = EINA_FALSE;
2083    window->tooltip.shown = EINA_FALSE;
2084
2085    /* Create window */
2086    window->elm_window = elm_win_add(NULL, "minibrowser-window", ELM_WIN_BASIC);
2087    elm_win_title_set(window->elm_window, APP_NAME);
2088    evas_object_smart_callback_add(window->elm_window, "delete,request", _window_deletion_cb, window);
2089
2090    /* Create window background */
2091    Evas_Object *bg = elm_bg_add(window->elm_window);
2092    elm_bg_color_set(bg, 193, 192, 191);
2093    evas_object_size_hint_weight_set(bg, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
2094    elm_win_resize_object_add(window->elm_window, bg);
2095    evas_object_show(bg);
2096
2097    /* Create conformant widget. */
2098    Evas_Object *conformant = elm_conformant_add(window->elm_window);
2099    evas_object_size_hint_weight_set(conformant, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
2100    elm_win_resize_object_add(window->elm_window, conformant);
2101    evas_object_show(conformant);
2102
2103    /* Create vertical layout */
2104    window->vertical_layout = elm_box_add(window->elm_window);
2105    elm_object_content_set(conformant, window->vertical_layout);
2106    elm_box_padding_set(window->vertical_layout, 0, 2);
2107    evas_object_size_hint_weight_set(window->vertical_layout, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
2108    evas_object_show(window->vertical_layout);
2109
2110    /* Create horizontal layout for top bar */
2111    window->horizontal_layout = elm_box_add(window->elm_window);
2112    elm_box_horizontal_set(window->horizontal_layout, EINA_TRUE);
2113    evas_object_size_hint_weight_set(window->horizontal_layout, EVAS_HINT_EXPAND, 0.0);
2114    evas_object_size_hint_align_set(window->horizontal_layout, EVAS_HINT_FILL, 0.0);
2115    elm_box_pack_end(window->vertical_layout, window->horizontal_layout);
2116    evas_object_show(window->horizontal_layout);
2117
2118    /* Create Back button */
2119    window->back_button = _create_toolbar_button(window->elm_window, "arrow_left");
2120    evas_object_smart_callback_add(window->back_button, "clicked", _back_button_clicked_cb, window);
2121    evas_object_smart_callback_add(window->back_button, "repeated", _back_button_longpress_cb, window);
2122    elm_object_tooltip_text_set(window->back_button, "Click to go back, longpress to see session history");
2123    elm_object_tooltip_window_mode_set(window->back_button, EINA_TRUE);
2124    elm_object_disabled_set(window->back_button, EINA_TRUE);
2125    evas_object_size_hint_weight_set(window->back_button, 0.0, EVAS_HINT_EXPAND);
2126    evas_object_size_hint_align_set(window->back_button, 0.0, 0.5);
2127    elm_box_pack_end(window->horizontal_layout, window->back_button);
2128    evas_object_show(window->back_button);
2129
2130    /* Create Forward button */
2131    window->forward_button = _create_toolbar_button(window->elm_window, "arrow_right");
2132    evas_object_smart_callback_add(window->forward_button, "clicked", _forward_button_clicked_cb, window);
2133    evas_object_smart_callback_add(window->forward_button, "repeated", _forward_button_longpress_cb, window);
2134    elm_object_tooltip_text_set(window->forward_button, "Click to go forward, longpress to see session history");
2135    elm_object_tooltip_window_mode_set(window->forward_button, EINA_TRUE);
2136    elm_object_disabled_set(window->forward_button, EINA_TRUE);
2137    evas_object_size_hint_weight_set(window->forward_button, 0.0, EVAS_HINT_EXPAND);
2138    evas_object_size_hint_align_set(window->forward_button, 0.0, 0.5);
2139    elm_box_pack_end(window->horizontal_layout, window->forward_button);
2140    evas_object_show(window->forward_button);
2141
2142    /* Create Search button */
2143    Evas_Object *search_button = _create_toolbar_button(window->elm_window, "toolbar/search");
2144    evas_object_smart_callback_add(search_button, "clicked", _search_button_clicked_cb, window);
2145    elm_object_tooltip_text_set(search_button, "Find text");
2146    elm_object_tooltip_window_mode_set(search_button, EINA_TRUE);
2147    evas_object_size_hint_weight_set(search_button, 0.0, EVAS_HINT_EXPAND);
2148    evas_object_size_hint_align_set(search_button, 1.0, 0.5);
2149    elm_box_pack_end(window->horizontal_layout, search_button);
2150    evas_object_show(search_button);
2151
2152    /* Create URL bar */
2153    window->url_bar = elm_entry_add(window->elm_window);
2154    elm_entry_scrollable_set(window->url_bar, EINA_TRUE);
2155    elm_scroller_policy_set(window->url_bar, ELM_SCROLLER_POLICY_OFF, ELM_SCROLLER_POLICY_OFF);
2156    elm_entry_single_line_set(window->url_bar, EINA_TRUE);
2157    elm_entry_cnp_mode_set(window->url_bar, ELM_CNP_MODE_PLAINTEXT);
2158    elm_entry_text_style_user_push(window->url_bar, "DEFAULT='font_size=18'");
2159    evas_object_smart_callback_add(window->url_bar, "activated", _url_bar_activated_cb, window);
2160    evas_object_smart_callback_add(window->url_bar, "clicked", _url_bar_clicked_cb, window);
2161    evas_object_size_hint_weight_set(window->url_bar, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
2162    evas_object_size_hint_align_set(window->url_bar, EVAS_HINT_FILL, EVAS_HINT_FILL);
2163    elm_box_pack_end(window->horizontal_layout, window->url_bar);
2164    evas_object_show(window->url_bar);
2165
2166    /* Create Refresh button */
2167    Evas_Object *refresh_button = _create_toolbar_button(window->elm_window, "refresh");
2168    evas_object_smart_callback_add(refresh_button, "clicked", _refresh_button_clicked_cb, window);
2169    elm_object_tooltip_text_set(refresh_button, "Reload page");
2170    elm_object_tooltip_window_mode_set(refresh_button, EINA_TRUE);
2171    evas_object_size_hint_weight_set(refresh_button, 0.0, EVAS_HINT_EXPAND);
2172    evas_object_size_hint_align_set(refresh_button, 1.0, 0.5);
2173    elm_box_pack_end(window->horizontal_layout, refresh_button);
2174    evas_object_show(refresh_button);
2175
2176    /* Create Stop button */
2177    Evas_Object *stop_button = _create_toolbar_button(window->elm_window, "close");
2178    evas_object_smart_callback_add(stop_button, "clicked", _stop_button_clicked_cb, window);
2179    elm_object_tooltip_text_set(stop_button, "Stop page load");
2180    elm_object_tooltip_window_mode_set(stop_button, EINA_TRUE);
2181    evas_object_size_hint_weight_set(stop_button, 0.0, EVAS_HINT_EXPAND);
2182    evas_object_size_hint_align_set(stop_button, 1.0, 0.5);
2183    elm_box_pack_end(window->horizontal_layout, stop_button);
2184    evas_object_show(stop_button);
2185
2186    /* Create Home button */
2187    Evas_Object *home_button = _create_toolbar_button(window->elm_window, "home");
2188    evas_object_smart_callback_add(home_button, "clicked", _home_button_clicked_cb, window);
2189    elm_object_tooltip_text_set(home_button, "Home page");
2190    elm_object_tooltip_window_mode_set(home_button, EINA_TRUE);
2191    evas_object_size_hint_weight_set(home_button, 0.0, EVAS_HINT_EXPAND);
2192    evas_object_size_hint_align_set(home_button, 1.0, 0.5);
2193    elm_box_pack_end(window->horizontal_layout, home_button);
2194    evas_object_show(home_button);
2195
2196    /* Create Search bar */
2197    window->search.search_bar = elm_box_add(window->elm_window);
2198    elm_box_horizontal_set(window->search.search_bar, EINA_TRUE);
2199    evas_object_size_hint_min_set(window->search.search_bar, SEARCH_FIELD_SIZE + 2 * SEARCH_BUTTON_SIZE, 0);
2200    evas_object_size_hint_align_set(window->search.search_bar, EVAS_HINT_FILL, EVAS_HINT_FILL);
2201    elm_box_pack_end(window->vertical_layout, window->search.search_bar);
2202
2203    /* Create Search field */
2204    window->search.search_field = elm_entry_add(window->elm_window);
2205    elm_entry_scrollable_set(window->search.search_field, EINA_TRUE);
2206    elm_scroller_policy_set(window->search.search_field, ELM_SCROLLER_POLICY_OFF, ELM_SCROLLER_POLICY_OFF);
2207    elm_entry_single_line_set(window->search.search_field, EINA_TRUE);
2208    elm_entry_cnp_mode_set(window->search.search_field, ELM_CNP_MODE_PLAINTEXT);
2209    elm_entry_text_style_user_push(window->search.search_field, "DEFAULT='font_size=14'");
2210    evas_object_smart_callback_add(window->search.search_field, "activated", _search_field_activated_cb, window);
2211    evas_object_smart_callback_add(window->search.search_field, "changed", _search_field_activated_cb, window);
2212    evas_object_smart_callback_add(window->search.search_field, "aborted", _search_field_aborted_cb, window);
2213    evas_object_smart_callback_add(window->search.search_field, "clicked", _search_field_clicked_cb, window);
2214    evas_object_size_hint_weight_set(window->search.search_field, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
2215    evas_object_size_hint_align_set(window->search.search_field, EVAS_HINT_FILL, EVAS_HINT_FILL);
2216    elm_box_pack_end(window->search.search_bar, window->search.search_field);
2217
2218    /* Create Search backward button */
2219    window->search.backward_button = _create_toolbar_button(window->elm_window, "arrow_up");
2220    evas_object_smart_callback_add(window->search.backward_button, "clicked", _search_backward_button_clicked_cb, window);
2221    elm_object_disabled_set(window->search.backward_button, EINA_FALSE);
2222    evas_object_size_hint_weight_set(window->search.backward_button, 0.0, EVAS_HINT_EXPAND);
2223    evas_object_size_hint_align_set(window->search.backward_button, 1.0, 0.5);
2224    evas_object_size_hint_min_set(window->search.backward_button, SEARCH_BUTTON_SIZE, SEARCH_BUTTON_SIZE);
2225    elm_box_pack_end(window->search.search_bar, window->search.backward_button);
2226
2227    /* Create Search forwardward button */
2228    window->search.forward_button = _create_toolbar_button(window->elm_window, "arrow_down");
2229    evas_object_smart_callback_add(window->search.forward_button, "clicked", _search_forward_button_clicked_cb, window);
2230    elm_object_disabled_set(window->search.forward_button, EINA_FALSE);
2231    evas_object_size_hint_weight_set(window->search.forward_button, 0.0, EVAS_HINT_EXPAND);
2232    evas_object_size_hint_align_set(window->search.forward_button, 1.0, 0.5);
2233    evas_object_size_hint_min_set(window->search.forward_button, SEARCH_BUTTON_SIZE, SEARCH_BUTTON_SIZE);
2234    elm_box_pack_end(window->search.search_bar, window->search.forward_button);
2235
2236    /* Create Search count field */
2237    window->search.search_field_count = elm_label_add(window->elm_window);
2238    evas_object_size_hint_weight_set(window->search.search_field_count, 0.0, EVAS_HINT_EXPAND);
2239    evas_object_size_hint_align_set(window->search.search_field_count, EVAS_HINT_FILL, EVAS_HINT_FILL);
2240    elm_object_text_set(window->search.search_field_count, "");
2241    elm_box_pack_end(window->search.search_bar, window->search.search_field_count);
2242
2243    /* Create Search Case Sensitive Option check box */
2244    window->search.search_case_check_box = elm_check_add(window->elm_window);
2245    elm_object_text_set(window->search.search_case_check_box, "Case Sensitive");
2246    evas_object_smart_callback_add(window->search.search_case_check_box, "changed", _search_case_option_changed, window);
2247    elm_box_pack_end(window->search.search_bar, window->search.search_case_check_box);
2248
2249    /* Create Search Word Start Option check box */
2250    window->search.search_word_start_check_box = elm_check_add(window->elm_window);
2251    elm_object_text_set(window->search.search_word_start_check_box, "Only Word Start");
2252    evas_object_smart_callback_add(window->search.search_word_start_check_box, "changed", _search_word_start_option_changed_cb, window);
2253    elm_box_pack_end(window->search.search_bar, window->search.search_word_start_check_box);
2254
2255    /* Create Search close button */
2256    window->search.close_button = _create_toolbar_button(window->elm_window, "close");
2257    evas_object_smart_callback_add(window->search.close_button, "clicked", _search_close_button_clicked_cb, window);
2258    elm_object_disabled_set(window->search.close_button, EINA_FALSE);
2259    evas_object_size_hint_weight_set(window->search.close_button, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
2260    evas_object_size_hint_align_set(window->search.close_button, 1.0, 0.5);
2261    evas_object_size_hint_min_set(window->search.close_button, SEARCH_BUTTON_SIZE, SEARCH_BUTTON_SIZE);
2262    elm_box_pack_end(window->search.search_bar, window->search.close_button);
2263
2264    /* Create history box */
2265    window->history.history_box = elm_box_add(window->elm_window);
2266    evas_object_size_hint_aspect_set(window->history.history_box, EVAS_ASPECT_CONTROL_VERTICAL, 1, 1);
2267    evas_object_size_hint_weight_set(window->history.history_box, EVAS_HINT_EXPAND , EVAS_HINT_EXPAND);
2268
2269    /* Create history list */
2270    window->history.history_list = elm_genlist_add(window->elm_window);
2271    evas_object_size_hint_weight_set(window->history.history_list, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
2272    evas_object_size_hint_align_set(window->history.history_list, EVAS_HINT_FILL, EVAS_HINT_FILL);
2273    elm_win_resize_object_add(window->elm_window, window->history.history_box);
2274    elm_box_pack_end(window->history.history_box, window->history.history_list);
2275
2276    /* Create ewk_view */
2277    Ewk_View_Smart_Class *ewkViewClass = miniBrowserViewSmartClass();
2278    ewkViewClass->run_javascript_alert = _javascript_alert_cb;
2279    ewkViewClass->run_javascript_confirm = _javascript_confirm_cb;
2280    ewkViewClass->run_javascript_prompt = _javascript_prompt_cb;
2281    ewkViewClass->run_javascript_before_unload_confirm = _javascript_before_unload_confirm_cb;
2282    ewkViewClass->window_geometry_get = _window_geometry_get;
2283    ewkViewClass->window_geometry_set = _window_geometry_set;
2284    ewkViewClass->fullscreen_enter = _fullscreen_enter_cb;
2285    ewkViewClass->fullscreen_exit = _fullscreen_exit_cb;
2286    ewkViewClass->window_create = _window_create_cb;
2287    ewkViewClass->window_close = _window_close_cb;
2288    ewkViewClass->popup_menu_show = _popup_menu_show;
2289    ewkViewClass->popup_menu_hide = _popup_menu_hide;
2290    ewkViewClass->context_menu_show = _context_menu_show;
2291    ewkViewClass->context_menu_hide = _context_menu_hide;
2292    ewkViewClass->input_picker_color_request = _color_picker_request_cb;
2293    ewkViewClass->input_picker_color_dismiss = _color_picker_dismiss_cb;
2294
2295    Evas *evas = evas_object_evas_get(window->elm_window);
2296    Evas_Smart *smart = evas_smart_class_new(&ewkViewClass->sc);
2297    window->ewk_view = ewk_view_add_with_configuration(evas, smart, configuration);
2298
2299    Ewk_Context *context = ewk_view_context_get(window->ewk_view);
2300    ewk_favicon_database_icon_change_callback_add(ewk_context_favicon_database_get(context), _icon_changed_cb, window);
2301
2302    ewk_view_theme_set(window->ewk_view, DEFAULT_THEME_DIR "/default.edj");
2303    if (device_pixel_ratio)
2304      ewk_view_device_pixel_ratio_set(window->ewk_view, (float)device_pixel_ratio);
2305    ewk_view_user_agent_set(window->ewk_view, user_agent_string);
2306    ewk_view_layout_fixed_set(window->ewk_view, fixed_layout_enabled);
2307
2308    if (touch_events_enabled) {
2309      ewk_view_touch_events_enabled_set(window->ewk_view, EINA_TRUE);
2310      ewk_view_mouse_events_enabled_set(window->ewk_view, EINA_FALSE);
2311    }
2312
2313    if (background_color_string) {
2314      int red, green, blue, alpha;
2315
2316      if (sscanf(background_color_string, "%d:%d:%d:%d", &red, &green, &blue, &alpha))
2317        ewk_view_bg_color_set(window->ewk_view, red, green, blue, alpha);
2318    }
2319
2320    /* Set the zoom level to default */
2321    window->current_zoom_level = DEFAULT_ZOOM_LEVEL;
2322
2323    elm_win_fullscreen_set(window->elm_window, fullscreen_enabled);
2324
2325    evas_object_smart_callback_add(window->ewk_view, "authentication,request", _authentication_request_cb, window);
2326    evas_object_smart_callback_add(window->ewk_view, "file,chooser,request", _file_chooser_request_cb, window);
2327    evas_object_smart_callback_add(window->ewk_view, "load,error", _error_cb, window);
2328    evas_object_smart_callback_add(window->ewk_view, "load,provisional,failed", _error_cb, window);
2329    evas_object_smart_callback_add(window->ewk_view, "load,progress", _progress_cb, window);
2330    evas_object_smart_callback_add(window->ewk_view, "title,changed", _title_changed_cb, window);
2331    evas_object_smart_callback_add(window->ewk_view, "url,changed", _url_changed_cb, window);
2332    evas_object_smart_callback_add(window->ewk_view, "back,forward,list,changed", _back_forward_list_changed_cb, window);
2333    evas_object_smart_callback_add(window->ewk_view, "text,found", _search_text_found_cb, window);
2334    evas_object_smart_callback_add(window->ewk_view, "tooltip,text,set", _tooltip_text_set, window);
2335    evas_object_smart_callback_add(window->ewk_view, "tooltip,text,unset", _tooltip_text_unset, window);
2336    evas_object_smart_callback_add(window->ewk_view, "policy,decision,navigation", _navigation_policy_decision_cb, window);
2337
2338    evas_object_event_callback_add(window->ewk_view, EVAS_CALLBACK_KEY_DOWN, _key_down_cb, window);
2339    evas_object_event_callback_add(window->ewk_view, EVAS_CALLBACK_MOUSE_DOWN, _mouse_down_cb, window);
2340
2341    evas_object_size_hint_weight_set(window->ewk_view, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
2342    evas_object_size_hint_align_set(window->ewk_view, EVAS_HINT_FILL, EVAS_HINT_FILL);
2343    elm_box_pack_before(window->vertical_layout, window->ewk_view, window->search.search_bar);
2344    evas_object_show(window->ewk_view);
2345
2346    evas_object_resize(window->elm_window, width ? width : window_width, height ? height : window_height);
2347    evas_object_show(window->elm_window);
2348    search_box_hide(window);
2349
2350    view_focus_set(window, EINA_TRUE);
2351    // Prevent window from stealing web view's focus on start up.
2352    elm_object_focus_allow_set(window->elm_window, EINA_FALSE);
2353
2354    evas_object_event_callback_add(window->ewk_view, EVAS_CALLBACK_MOUSE_IN, _mouse_in_cb, window);
2355    evas_object_event_callback_add(window->ewk_view, EVAS_CALLBACK_MOUSE_OUT, _mouse_out_cb, window);
2356    evas_object_event_callback_add(window->ewk_view, EVAS_CALLBACK_MOUSE_MOVE, _mouse_move_cb, window);
2357    evas_object_event_callback_add(window->ewk_view, EVAS_CALLBACK_MOUSE_WHEEL, _mouse_wheel_cb, window);
2358    evas_object_event_callback_add(window->elm_window, EVAS_CALLBACK_RESIZE, _window_resize_cb, window);
2359
2360    elm_button_autorepeat_set(window->back_button, EINA_TRUE);
2361    elm_button_autorepeat_set(window->forward_button, EINA_TRUE);
2362    elm_button_autorepeat_initial_timeout_set(window->back_button, LONGPRESS_INTERVAL_SECONDS);
2363    elm_button_autorepeat_initial_timeout_set(window->forward_button, LONGPRESS_INTERVAL_SECONDS);
2364
2365    return window;
2366 }
2367
2368 static Ewk_View_Configuration* configuration()
2369 {
2370     static Ewk_View_Configuration* default_configuration = 0;
2371
2372     if (default_configuration)
2373       return default_configuration;
2374
2375     default_configuration = ewk_view_configuration_new();
2376
2377     Ewk_Settings* settings = ewk_view_configuration_settings_get(default_configuration);
2378     ewk_settings_file_access_from_file_urls_allowed_set(settings, EINA_TRUE);
2379     ewk_settings_encoding_detector_enabled_set(settings, encoding_detector_enabled);
2380     ewk_settings_frame_flattening_enabled_set(settings, frame_flattening_enabled);
2381     ewk_settings_local_storage_enabled_set(settings, local_storage_enabled);
2382     ewk_settings_offline_web_application_cache_enabled_set(settings, offline_web_application_cache_enabled);
2383     INFO("HTML5 local storage is %s for this view.", local_storage_enabled ? "enabled" : "disabled");
2384     ewk_settings_developer_extras_enabled_set(settings, EINA_TRUE);
2385     ewk_settings_preferred_minimum_contents_width_set(settings, 0);
2386     ewk_text_checker_continuous_spell_checking_enabled_set(spell_checking_enabled);
2387     ewk_settings_web_security_enabled_set(settings, web_security_enabled);
2388
2389     return default_configuration;
2390 }
2391
2392 static Ewk_Cookie_Accept_Policy
2393 parse_cookies_policy(const char *input_string)
2394 {
2395    if (!strcmp(input_string, "always"))
2396      return EWK_COOKIE_ACCEPT_POLICY_ALWAYS;
2397    if (!strcmp(input_string, "never"))
2398      return EWK_COOKIE_ACCEPT_POLICY_NEVER;
2399    if (strcmp(input_string, "no-third-party"))
2400      INFO("Unrecognized type for cookies policy: %s.", input_string);
2401    return EWK_COOKIE_ACCEPT_POLICY_NO_THIRD_PARTY;
2402 }
2403
2404 static void
2405 parse_window_size(const char *input_string, int *width, int *height)
2406 {
2407    static const unsigned max_length = 4;
2408    int parsed_width;
2409    int parsed_height;
2410    char **arr;
2411    unsigned elements;
2412
2413    arr = eina_str_split_full(input_string, "x", 0, &elements);
2414
2415    if (elements == 2 && (strlen(arr[0]) <= max_length) && (strlen(arr[1]) <= max_length)) {
2416      parsed_width = atoi(arr[0]);
2417      if (width && parsed_width)
2418        *width = parsed_width;
2419
2420      parsed_height = atoi(arr[1]);
2421      if (height && parsed_height)
2422        *height = parsed_height;
2423    }
2424
2425    free(arr[0]);
2426    free(arr);
2427 }
2428
2429 EAPI_MAIN int
2430 elm_main(int argc, char *argv[])
2431 {
2432    int args = 1;
2433    unsigned char quitOption = 0;
2434    Browser_Window *window;
2435    char *window_size_string = NULL;
2436    char *cookies_policy_string = NULL;
2437
2438    Ecore_Getopt_Value values[] = {
2439      ECORE_GETOPT_VALUE_STR(evas_engine_name),
2440      ECORE_GETOPT_VALUE_STR(window_size_string),
2441      ECORE_GETOPT_VALUE_STR(user_agent_string),
2442      ECORE_GETOPT_VALUE_STR(extensions_path),
2443      ECORE_GETOPT_VALUE_DOUBLE(device_pixel_ratio),
2444      ECORE_GETOPT_VALUE_BOOL(quitOption),
2445      ECORE_GETOPT_VALUE_BOOL(encoding_detector_enabled),
2446      ECORE_GETOPT_VALUE_STR(background_color_string),
2447      ECORE_GETOPT_VALUE_BOOL(frame_flattening_enabled),
2448      ECORE_GETOPT_VALUE_BOOL(local_storage_enabled),
2449      ECORE_GETOPT_VALUE_BOOL(offline_web_application_cache_enabled),
2450      ECORE_GETOPT_VALUE_BOOL(fullscreen_enabled),
2451      ECORE_GETOPT_VALUE_BOOL(spell_checking_enabled),
2452      ECORE_GETOPT_VALUE_BOOL(touch_events_enabled),
2453      ECORE_GETOPT_VALUE_BOOL(fixed_layout_enabled),
2454      ECORE_GETOPT_VALUE_STR(cookies_policy_string),
2455      ECORE_GETOPT_VALUE_BOOL(web_security_enabled),
2456      ECORE_GETOPT_VALUE_BOOL(separated_process_enabled),
2457      ECORE_GETOPT_VALUE_BOOL(quitOption),
2458      ECORE_GETOPT_VALUE_BOOL(quitOption),
2459      ECORE_GETOPT_VALUE_BOOL(quitOption),
2460      ECORE_GETOPT_VALUE_NONE
2461    };
2462
2463    efreet_cache_update = 0;
2464
2465    if (!ewk_init())
2466      return EXIT_FAILURE;
2467
2468    _log_domain_id = eina_log_domain_register("minibrowser", EINA_COLOR_YELLOW);
2469
2470    ewk_view_smart_class_set(miniBrowserViewSmartClass());
2471
2472    ecore_app_args_set(argc, (const char **) argv);
2473    args = ecore_getopt_parse(&options, values, argc, argv);
2474
2475    if (args < 0)
2476      return quit(EINA_FALSE, "Could not parse options.");
2477
2478    if (quitOption)
2479      return quit(EINA_TRUE, NULL);
2480
2481    if (evas_engine_name)
2482      elm_config_accel_preference_set(evas_engine_name);
2483    else {
2484      evas_engine_name = "opengl:depth24:stencil8";
2485      elm_config_accel_preference_set(evas_engine_name);
2486    }
2487
2488    Ewk_Context *context = ewk_context_default_get();
2489
2490    if (separated_process_enabled)
2491      ewk_context_web_process_count_limit_set(context, 0);
2492
2493    // Enable favicon database.
2494    ewk_context_favicon_database_directory_set(context, NULL);
2495
2496    // Use a proper cache model.
2497    ewk_context_cache_model_set(context, EWK_CACHE_MODEL_PRIMARY_WEBBROWSER);
2498
2499    if (cookies_policy_string) {
2500      Ewk_Cookie_Accept_Policy cookie_policy = parse_cookies_policy(cookies_policy_string);
2501      ewk_cookie_manager_accept_policy_set(ewk_context_cookie_manager_get(context), cookie_policy);
2502
2503      if (cookie_policy == EWK_COOKIE_ACCEPT_POLICY_ALWAYS) {
2504        const char cookie_storage_directory[] = "/tmp/ewebkit2_minibrowser_cookie/";
2505        mkdir(cookie_storage_directory, S_IRWXU);
2506        char storage_name[64];
2507        snprintf(storage_name, sizeof(storage_name), "%stxt-cookie", cookie_storage_directory);
2508        ewk_cookie_manager_persistent_storage_set(ewk_context_cookie_manager_get(context), storage_name, EWK_COOKIE_PERSISTENT_STORAGE_TEXT);
2509      }
2510    }
2511
2512    if (window_size_string)
2513      parse_window_size(window_size_string, &window_width, &window_height);
2514
2515    window = window_create(configuration(), 0, 0);
2516    if (!window)
2517      return quit(EINA_FALSE, "Could not create browser window.");
2518
2519    // Set callbacks for download events.
2520    ewk_context_download_callbacks_set(context, _download_request_cb, _download_failed_cb, 0, _download_finished_cb, window);
2521
2522    if (args < argc) {
2523      char *url = url_from_user_input(argv[args]);
2524      url_load_from_user_input(window->ewk_view, url);
2525      free(url);
2526    } else
2527      ewk_view_url_set(window->ewk_view, DEFAULT_URL);
2528
2529    windows = eina_list_append(windows, window);
2530
2531    elm_run();
2532
2533    return quit(EINA_TRUE, NULL);
2534 }
2535 ELM_MAIN()
2536