main.c (12855B)
1 /* 2 (c) 2009 by Leon Winter 3 (c) 2009-2012 by Hannes Schueller 4 (c) 2009-2010 by Matto Fransen 5 (c) 2010-2011 by Hans-Peter Deifel 6 (c) 2010-2011 by Thomas Adam 7 (c) 2011 by Albert Kim 8 (c) 2011 by Daniel Carl 9 (c) 2012 by Matthew Carter 10 see LICENSE file 11 */ 12 13 #include <Elementary.h> 14 #include <EWebKit2.h> 15 16 #include "viking_state.h" 17 #include "viking.h" 18 #include "utilities.h" 19 #include "window.h" 20 #include "buffer.h" 21 22 23 /* functions */ 24 EAPI_MAIN int elm_main(int argc, char *argv[]); 25 const char *uri_sanitize(const char *); 26 27 static Eina_Bool 28 session_save_cb(void *data) 29 { 30 Window_Data *wd; 31 Buffer_Data *bd; 32 Eina_List *buffer_iter, *win_iter; 33 Session_Item *si; 34 App_Data *ad = data; 35 Eina_Bool focused; 36 // int sx, sy; 37 38 /* TODO: only save when something has changed */ 39 if (!config_restore_state_get(ad->config)) goto end; 40 41 EINA_LIST_FOREACH(ad->windows, win_iter, wd) { 42 43 EINA_LIST_FOREACH(wd->buffer_list, buffer_iter, bd) { 44 45 Evas_Object *view = bd->view; 46 focused = (bd == wd->cur_buf); 47 48 si = evas_object_data_get(bd->view, "session"); 49 if (!si) 50 printf("buffer %p doesn't have a Session_Item, ignoring\n", bd); 51 52 session_item_url_set(si, ewk_view_url_get(view)); 53 54 /* 55 ewk_frame_scroll_pos_get(frame, &sx, &sy); 56 if (session_item_scroll_x_get(si) != sx || session_item_scroll_y_get(si) != sy) { 57 session_item_scroll_x_set(si, sx); 58 session_item_scroll_y_set(si, sy); 59 } 60 */ 61 62 if (session_item_focused_get(si) != focused) 63 session_item_focused_set(si, focused); 64 } 65 } 66 67 session_save(ad->session, NULL); 68 end: 69 return ECORE_CALLBACK_RENEW; 70 } 71 72 static Eina_Bool 73 session_restore(App_Data *ad) 74 { 75 Eina_List *windows, *window_iter; 76 Eina_List *buffers, *buffers_iter; 77 Session_Window *window; 78 Session_Item *buffer; 79 Window_Data *wd; 80 Buffer_Data *bd, *focused_buffer = NULL; 81 int n_tabs = 0; 82 83 windows = session_windows_list_get(ad->session); 84 EINA_LIST_FOREACH(windows, window_iter, window) { 85 86 buffers = session_window_tabs_list_get(window); 87 wd = window_add(ad, window); 88 EINA_LIST_FOREACH(buffers, buffers_iter, buffer) { 89 bd = buffer_add(0, wd, session_item_url_get(buffer), buffer); 90 // session_restore_delayed_scroll(win->current_view, item); 91 if (session_item_focused_get(buffer)) 92 focused_buffer = bd; 93 n_tabs++; 94 } 95 window_main_buffer_set(focused_buffer); 96 } 97 98 return !!n_tabs; 99 } 100 101 static void 102 hist_nav_cb(const Evas_Object *view, Ewk_Navigation_Data *nav_data, void *data) 103 { 104 Hist_Item *item; 105 App_Data *ad = data; 106 Eina_Strbuf *proto = eina_strbuf_new(); 107 Eina_Stringshare *title = ewk_navigation_data_title_get(nav_data); 108 Eina_Stringshare *url = ewk_navigation_data_url_get(nav_data); 109 110 if (strncmp(url, "http://", 7) == 0) { 111 eina_strbuf_append(proto, "http"); 112 url += 7; 113 } 114 else if (strncmp(url, "https://", 8) == 0) { 115 eina_strbuf_append(proto, "https"); 116 url += 8; 117 } 118 119 item = hist_items_get(ad->history, url); 120 if (item && hist_item_enabled_get(item)) { 121 hist_item_visit_count_set(item, hist_item_visit_count_get(item) + 1); 122 hist_item_last_visit_set(item, ecore_time_unix_get()); 123 hist_item_title_set(item, title); 124 hist_item_proto_set(item, eina_strbuf_string_get(proto)); 125 } 126 else if (!item && config_enable_history_get(ad->config)) { 127 hist_items_add(ad->history, url, hist_item_new( 128 EINA_TRUE, 129 title, 130 url, 131 eina_strbuf_string_get(proto), 132 1, 133 ecore_time_unix_get())); 134 } 135 136 eina_strbuf_free(proto); 137 } 138 139 static void 140 hist_redir_cb(const Evas_Object *view, const char *source_url, const char *dest_url, void *data) 141 { 142 int prefix, min, suffix, src_len, dest_len; 143 144 if (strcmp(ewk_view_url_get(view), dest_url) != 0) { 145 printf("hist_redir_cb() not showing third party redirect\n"); 146 return; 147 } 148 149 src_len = strlen(source_url); 150 dest_len = strlen(dest_url); 151 152 if (src_len < dest_len) 153 min = src_len; 154 else 155 min = dest_len; 156 157 prefix = 0; 158 while (source_url[prefix] == dest_url[prefix] && prefix < min) 159 prefix++; 160 161 suffix = 0; 162 while (source_url[src_len - suffix - 1] == dest_url[dest_len - suffix - 1] && suffix < min) 163 suffix++; 164 165 // printf("redir: prefix = %i, suffix = %i, min = %i\n", prefix, suffix, min); 166 167 if (min - suffix - prefix < 0) { 168 printf("redirecion() from %s to %s\n", source_url, dest_url); 169 return; 170 } 171 172 Eina_Strbuf *buf = eina_strbuf_new(); 173 eina_strbuf_append_n(buf, source_url, prefix); 174 eina_strbuf_append(buf, "{"); 175 eina_strbuf_append_n(buf, source_url + prefix, src_len - suffix - prefix); 176 eina_strbuf_append(buf, " => "); 177 eina_strbuf_append_n(buf, dest_url + prefix, dest_len - suffix - prefix); 178 eina_strbuf_append(buf, "}"); 179 eina_strbuf_append_n(buf, source_url + src_len - suffix, suffix); 180 181 printf("redirection() %s\n", eina_strbuf_string_steal(buf)); 182 } 183 184 static void 185 hist_client_redir_cb(const Evas_Object *view, const char *source_url, const char *dest_url, void *data) 186 { 187 printf("client cur url = %s\n", ewk_view_url_get(view)); 188 printf("client "); 189 hist_redir_cb(view, source_url, dest_url, data); 190 } 191 192 static void 193 hist_server_redir_cb(const Evas_Object *view, const char *source_url, const char *dest_url, void *data) 194 { 195 printf("server cur url = %s\n", ewk_view_url_get(view)); 196 printf("server "); 197 hist_redir_cb(view, source_url, dest_url, data); 198 } 199 200 static void 201 hist_visited_cb(void *data) 202 { 203 App_Data *ad = data; 204 void *hash_data; 205 Eina_Strbuf *url_buf = eina_strbuf_new(); 206 Eina_Iterator *it = eina_hash_iterator_tuple_new(hist_items_hash_get(ad->history)); 207 208 while (eina_iterator_next(it, &hash_data)) { 209 Eina_Hash_Tuple *t = hash_data; 210 Hist_Item *hist_item = t->data; 211 212 eina_strbuf_append(url_buf, hist_item_proto_get(hist_item)); 213 eina_strbuf_append(url_buf, "://"); 214 eina_strbuf_append(url_buf, hist_item_url_get(hist_item)); 215 ewk_context_visited_link_add(ewk_context_default_get(), eina_strbuf_string_get(url_buf)); 216 eina_strbuf_reset(url_buf); 217 } 218 219 eina_iterator_free(it); 220 } 221 222 static void 223 hist_title_updated_cb(const Evas_Object *vew, const char *title, const char *url, void *data) 224 { 225 // printf("title_update() %s has new title %s\n", url, title); 226 } 227 228 static void 229 generic_url_scheme_request_cb(Ewk_Url_Scheme_Request *request, void *user_data) 230 { 231 Eina_Strbuf *buf = eina_strbuf_new(); 232 char *handler = user_data; 233 const char *url = ewk_url_scheme_request_url_get(request); 234 eina_strbuf_append_printf(buf, "%s \"%s\"\n", handler, url); 235 printf("%s\n", eina_strbuf_string_get(buf)); 236 ecore_exe_run(eina_strbuf_string_steal(buf), NULL); 237 // ewk_url_scheme_request_finish(request, NULL, 0, "text/html"); 238 } 239 240 static void 241 setup_main_callbacks(App_Data *ad, const char *cookie_path) 242 { 243 int i; 244 Ewk_Cookie_Manager *cookie_manager; 245 Ewk_Context *context = ewk_context_default_get(); 246 247 ewk_context_cache_model_set(context, EWK_CACHE_MODEL_PRIMARY_WEBBROWSER); 248 ewk_context_favicon_database_directory_set(context, NULL); 249 250 /* set cookie policy to use text file and no third party cookies */ 251 cookie_manager = ewk_context_cookie_manager_get(context); 252 ewk_cookie_manager_persistent_storage_set(cookie_manager, cookie_path, 253 EWK_COOKIE_PERSISTENT_STORAGE_TEXT); 254 ewk_cookie_manager_accept_policy_set(cookie_manager, 255 EWK_COOKIE_ACCEPT_POLICY_NO_THIRD_PARTY); 256 257 /* history hooks */ 258 ewk_context_history_callbacks_set( 259 context, 260 hist_nav_cb, 261 hist_client_redir_cb, 262 hist_server_redir_cb, 263 hist_title_updated_cb, 264 hist_visited_cb, 265 ad 266 ); 267 268 /* url scheme registration */ 269 URIHandler uri_handlers[] = { 270 { "mailto", "terminology -e mutt" }, 271 { "ftp", "terminology -e wget ftp://" }, 272 { "magnet", "xterm -e rtorrent" }, 273 }; 274 275 for (i = 0; i < LENGTH(uri_handlers); i++) 276 ewk_context_url_scheme_register(context, uri_handlers[i].handle, 277 generic_url_scheme_request_cb, uri_handlers[i].handler); 278 } 279 280 281 static Eina_Bool 282 _client_add(void *data, int type, void *event_info) 283 { 284 Ecore_Con_Event_Server_Add *ev = event_info; 285 char *url = data; 286 287 ecore_con_server_send(ev->server, url, strlen(url)); 288 ecore_con_server_flush(ev->server); 289 290 ecore_main_loop_quit(); 291 return ECORE_CALLBACK_RENEW; 292 } 293 294 static Eina_Bool 295 _client_del(void *data, int type, void *event_info) 296 { 297 Ecore_Con_Event_Server_Del *ev = event_info; 298 if (!ev->server) 299 { 300 printf("Failed to establish connection to the server.\nExiting.\n"); 301 ecore_main_loop_quit(); 302 return ECORE_CALLBACK_RENEW; 303 } 304 305 ecore_con_server_del(ev->server); 306 307 ecore_main_loop_quit(); 308 return ECORE_CALLBACK_RENEW; 309 } 310 311 static Eina_Bool 312 _server_data(void *data, int type, void *event_info) 313 { 314 Ecore_Con_Event_Client_Data *ev = event_info; 315 char *uri = ev->data; 316 App_Data *ad = data; 317 318 Window_Data *wd = window_add(ad, NULL); 319 buffer_add(SwitchToBuffer, wd, uri, NULL); 320 321 return ECORE_CALLBACK_RENEW; 322 } 323 324 static Eina_Bool 325 _server_del(void *data, int type, void *event_info) 326 { 327 Ecore_Con_Event_Client_Del *ev = event_info; 328 329 if (!ev->client) 330 return ECORE_CALLBACK_RENEW; 331 332 ecore_con_client_del(ev->client); 333 return ECORE_CALLBACK_RENEW; 334 } 335 336 EAPI_MAIN int 337 elm_main(int argc, char *argv[]) 338 { 339 App_Data *ad; 340 char *basename, path[PATH_MAX]; 341 const char *uri = NULL; 342 Config *config; 343 Hist *hist; 344 Session *session; 345 size_t dirlen; 346 Ecore_Timer *session_save_timer = NULL; 347 Ecore_Con_Server *svr; 348 349 if (argc == 2) 350 uri = uri_sanitize(argv[1]); 351 352 ecore_con_init(); 353 if ((svr = ecore_con_server_connect(ECORE_CON_LOCAL_USER, "viking", 0, NULL))) { 354 if (!uri) 355 uri = DEFAULT_URL; 356 357 ecore_event_handler_add(ECORE_CON_EVENT_SERVER_ADD, _client_add, uri); 358 ecore_event_handler_add(ECORE_CON_EVENT_SERVER_DEL, _client_del, uri); 359 360 ecore_main_loop_begin(); 361 ecore_con_shutdown(); 362 elm_shutdown(); 363 exit(0); 364 } 365 366 if (!ewk_init()) 367 return EXIT_FAILURE; 368 369 ewk_view_smart_class_set(miniBrowserViewSmartClass()); 370 371 eet_init(); 372 viking_state_init(); 373 374 /* calloc zeros the memory!! */ 375 ad = calloc(1, sizeof(App_Data)); 376 if (!ad) return -1; 377 378 /* see if ~/.config/viking exists and create it if not */ 379 dirlen = snprintf(path, sizeof(path), "%s/viking", efreet_config_home_get()); 380 if (dirlen >= sizeof(path)) 381 ERR("Path is too long: %s/viking", efreet_config_home_get()); 382 if (!ecore_file_mkpath(path)) 383 ERR("Could not create %s", path); 384 385 basename = path + dirlen; 386 basename[0] = '/'; 387 basename++; 388 dirlen++; 389 390 eina_strlcpy(basename, "config.eet", sizeof(path) - dirlen); 391 if (!(config = config_load(path))) { 392 config = config_new(EINA_TRUE /* allow_popup */, 393 EINA_TRUE /* enable_auto_load_images */, 394 EINA_TRUE /* enable_auto_shrink_images */, 395 EINA_TRUE /* enable_javascript */, 396 EINA_FALSE /* enable_private_mode */, 397 EINA_TRUE, /* global history */ 398 DEFAULT_URL /* home_page */, 399 NULL /* proxy */, 400 EINA_TRUE /* restore_state */, 401 NULL, /* user agent string */ 402 EINA_FALSE /* frame_flattening */, 403 EINA_FALSE /* text_only_zoom */, 404 12 /* minimum_font_size */, 405 EWK_COOKIE_ACCEPT_POLICY_NO_THIRD_PARTY); 406 if (!config_save(config, path)) 407 ERR("Could not save new configuration at %s", path); 408 } 409 410 if (!(hist = hist_load(path))) { 411 hist = hist_new(); 412 if (!hist_save(hist, path)) 413 ERR("Could not save new history file at %s", path); 414 } 415 416 if (!(session = session_load(path))) { 417 session = session_new(NULL); 418 if (!session_save(session, path)) 419 ERR("Could not save new session file at %s", path); 420 } 421 422 eina_strlcpy(basename, "cookies.txt", sizeof(path) - dirlen); 423 setup_main_callbacks(ad, path); 424 425 session_save_timer = ecore_timer_loop_add(30, session_save_cb, ad); 426 if (!session_save_timer) 427 ERR("Could not register session save timer"); 428 429 elm_theme_overlay_add(NULL, "./default.edj"); 430 elm_config_engine_set("opengl_x11"); 431 432 setup_modkeys(ad); 433 ad->config = config; 434 ad->history = hist; 435 ad->session = session; 436 ad->session_save_timer = session_save_timer; 437 ad->keylistroot = make_keyslist(); 438 439 if (!(svr = ecore_con_server_add(ECORE_CON_LOCAL_USER, "viking", 0, NULL))) { 440 printf("could not create server -- this is bad!\n"); 441 exit(1); 442 } 443 444 ecore_event_handler_add(ECORE_CON_EVENT_CLIENT_DEL, _server_del, ad); 445 ecore_event_handler_add(ECORE_CON_EVENT_CLIENT_DATA, _server_data, ad); 446 ecore_con_server_timeout_set(svr, 10); 447 // ecore_con_server_client_limit_set(svr, 3, 0); 448 449 /* try to restore session */ 450 if (session_windows_count(session) > 0 && session_restore(ad)) 451 printf("session restored successfully.\n"); 452 else 453 buffer_add(SwitchToBuffer, window_add(ad, NULL), uri, NULL); 454 455 elm_run(); 456 457 session_save_cb(ad); 458 config_save(ad->config, NULL); 459 hist_save(ad->history, NULL); 460 if (ad->session_save_timer) 461 ecore_timer_del(ad->session_save_timer); 462 463 // printf("viking was up for %0.3f seconds\n", ecore_con_server_uptime_get(svr)); 464 elm_shutdown(); 465 viking_state_shutdown(); 466 eet_shutdown(); 467 ecore_con_shutdown(); 468 469 config_free(ad->config); 470 hist_free(ad->history); 471 session_free(ad->session); 472 eina_list_free(ad->windows); 473 eina_list_free(ad->downloads); 474 eina_list_free(ad->keylistroot); 475 free(ad->modkeys); 476 free(ad); 477 478 return 0; 479 } 480 ELM_MAIN() 481