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