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