├── .gitignore ├── README.md ├── blacklist ├── blacklist.cpp ├── blacklist.h ├── browser.cpp ├── browser.h ├── header.h ├── library.h ├── main.cpp ├── makefile ├── model.cpp ├── model.h ├── screenshot ├── browser.png └── browser2.png ├── tab.cpp ├── tab.h ├── tproject.config ├── webview.cpp └── webview.h /.gitignore: -------------------------------------------------------------------------------- 1 | main 2 | cookie 3 | data.db 4 | crash 5 | *.o 6 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ### Description 2 | Small Browser for Fun 3 | 4 | ### Controls: 5 | * F2: Create new tab 6 | * F3: Delete tab 7 | * F6: Duplicate tab 8 | 9 | ### Screenshots: 10 | ![alt tag](/screenshot/browser.png) 11 | ![alt tag](/screenshot/browser2.png) 12 | 13 | ### Dependencies: 14 | * Webkit 15 | * Webkit GTK 16 | * Clang 17 | * CCache 18 | * GTK 3.0 19 | * GTKMM 20 | * Sqlite3 21 | * Make 22 | 23 | ### Build: 24 | make 25 | 26 | ### Author 27 | B.Thach 28 | -------------------------------------------------------------------------------- /blacklist: -------------------------------------------------------------------------------- 1 | kinja.com 2 | lifehacker.com 3 | serve.popads.net 4 | clickadu.com 5 | popcash.net 6 | -------------------------------------------------------------------------------- /blacklist.cpp: -------------------------------------------------------------------------------- 1 | #include "blacklist.h" 2 | #include 3 | #include 4 | 5 | BlackList::BlackList(std::string path) 6 | : exe_path(path) 7 | { 8 | loadList(); 9 | } 10 | 11 | void BlackList::loadList() { 12 | std::ifstream file(exe_path + "/blacklist"); 13 | std::string line; 14 | 15 | if (file.is_open()) { 16 | while(getline(file, line)) { 17 | black_list.push_back(line); 18 | std::cout << line << "\n"; 19 | } 20 | file.close(); 21 | } 22 | } 23 | 24 | bool BlackList::isInBlackList(std::string address) { 25 | for(auto& blackUri : black_list) { 26 | if(address.find(blackUri) != std::string::npos) { 27 | return true; 28 | } 29 | } 30 | return false; 31 | } 32 | -------------------------------------------------------------------------------- /blacklist.h: -------------------------------------------------------------------------------- 1 | #ifndef BLACK_LIST_H 2 | #define BLACK_LIST_H 3 | #include 4 | #include 5 | 6 | class BlackList { 7 | public: 8 | BlackList(std::string path); 9 | void loadList(); 10 | bool isInBlackList(std::string address); 11 | 12 | private: 13 | std::string exe_path; 14 | std::vector black_list; 15 | }; 16 | 17 | #endif 18 | -------------------------------------------------------------------------------- /browser.cpp: -------------------------------------------------------------------------------- 1 | #include "browser.h" 2 | 3 | int TITLE_LENGTH = 20; 4 | int LIMIT_TAB = 8; 5 | ustring app_name = "DBT Browser"; 6 | 7 | ustring remove_http_string(ustring address) { 8 | string r = address; 9 | //~ cout << "full address: " << r << endl; 10 | if (address.find("http://www.") == 0) { 11 | r.erase(0, 11); 12 | //~ cout << "after trim: " << r << endl; 13 | } 14 | else if (address.find("https://www.") == 0) { 15 | r.erase(0, 12); 16 | //~ cout << "after trim: " << r << endl; 17 | } 18 | else if (address.find("http://") == 0) { 19 | r.erase(0, 7); 20 | //~ cout << "after trim: " << r << endl; 21 | } 22 | else if (address.find("https://") == 0) { 23 | r.erase(0, 8); 24 | //~ cout << "after trim: " << r << endl; 25 | } 26 | 27 | // xoa dau / cuoi string 28 | if (r.back() == '/') { 29 | r.pop_back(); 30 | //~ cout << "after trim: " << r << endl; 31 | } 32 | 33 | return r; 34 | } 35 | 36 | void find_and_replace(ustring& content, const string& search, const string& replace) { 37 | auto pos = content.find(search); 38 | while(pos != std::string::npos) { 39 | content.replace(pos, search.length(), replace); 40 | pos = content.find(search, pos); 41 | } 42 | } 43 | 44 | Browser::~Browser() { 45 | 46 | } 47 | 48 | static gboolean webview_decide_policy(WebKitWebView *webview, WebKitPolicyDecision *decision, 49 | WebKitPolicyDecisionType type, void* thisclass) { 50 | 51 | //~ Browser* browser = (Browser*)thisclass; 52 | 53 | switch (type) { 54 | case WEBKIT_POLICY_DECISION_TYPE_NAVIGATION_ACTION: { 55 | //~ cout << "WEBKIT_POLICY_DECISION_TYPE_NAVIGATION_ACTION" << endl; 56 | auto navigation_decision = WEBKIT_NAVIGATION_POLICY_DECISION(decision); 57 | auto navigation_action = webkit_navigation_policy_decision_get_navigation_action(navigation_decision); 58 | int modifiers = webkit_navigation_action_get_modifiers(navigation_action); 59 | 60 | // get request uri va tao new tab 61 | auto request = webkit_navigation_action_get_request(navigation_action); 62 | auto address = webkit_uri_request_get_uri(request); 63 | 64 | if (address) { 65 | Browser* browser = (Browser*)thisclass; 66 | 67 | // control click 68 | if (modifiers == GDK_CONTROL_MASK) { 69 | webkit_policy_decision_ignore(decision); // bo request link hien tai 70 | browser->create_new_tab(address, false); // ko switch to last tab 71 | } 72 | } 73 | 74 | break; 75 | } 76 | case WEBKIT_POLICY_DECISION_TYPE_NEW_WINDOW_ACTION: 77 | //~ webkit_policy_decision_ignore(decision); 78 | //~ cout << "WEBKIT_POLICY_DECISION_TYPE_NEW_WINDOW_ACTION" << endl; 79 | break; 80 | 81 | case WEBKIT_POLICY_DECISION_TYPE_RESPONSE: { 82 | //~ cout << "WEBKIT_POLICY_DECISION_TYPE_NEW_WINDOW_ACTION" << endl; 83 | //~ WebKitResponsePolicyDecision* response = WEBKIT_RESPONSE_POLICY_DECISION(decision); 84 | //~ auto request = webkit_response_policy_decision_get_request(response); 85 | //~ auto address = webkit_uri_request_get_uri(request); 86 | //~ if (address) { 87 | //~ // cout << "uri response: " << address << "\n"; 88 | //~ Browser* browser = (Browser*)thisclass; 89 | //~ if (browser->checkBlackListAddress(address)) { 90 | //~ // cout << "is in black list" << "\n"; 91 | //~ webkit_policy_decision_ignore(decision); 92 | //~ } 93 | //~ } 94 | 95 | // not use 96 | //~ if(!webkit_response_policy_decision_is_mime_type_supported(response)) { 97 | //~ webkit_policy_decision_ignore(decision); 98 | //~ } 99 | break; 100 | } 101 | 102 | default: 103 | //~ cout << "WEBKIT_POLICY_DEFAULT" << endl; 104 | //~ cout << "DEFAULT WEBKIT POLICY" << endl; 105 | return false; 106 | } 107 | 108 | return true; 109 | } 110 | 111 | bool Browser::checkBlackListAddress(std::string address) { 112 | return blacklist.isInBlackList(address); 113 | } 114 | 115 | 116 | static GtkWidget* webview_create(WebKitWebView* webview, WebKitNavigationAction *navigation_action, void* thisclass) { 117 | 118 | //~ auto type = webkit_navigation_action_get_navigation_type(navigation_action); 119 | //~ cout << "create type ==== ::: " << type << endl; 120 | 121 | auto request = webkit_navigation_action_get_request(navigation_action); 122 | const gchar* address = webkit_uri_request_get_uri(request); 123 | if (address) { 124 | Browser* browser = (Browser*)thisclass; 125 | // CHEAT: tam thoi cheat cho nay ko cho link vao mot so site gay crash va ads 126 | if (browser->checkBlackListAddress(address)) { 127 | return NULL; 128 | } 129 | browser->create_new_tab(address, false); // false: dont switch to last tab 130 | } 131 | 132 | return NULL; 133 | } 134 | 135 | static void webview_load_change (WebKitWebView* webview, WebKitLoadEvent load_event, void* thisclass) { 136 | 137 | switch (load_event) { 138 | case WEBKIT_LOAD_STARTED: { 139 | //~ cout << "WEBKIT_LOAD_STARTED" << endl; 140 | // load address 141 | const gchar* address = webkit_web_view_get_uri(webview); 142 | if (address) { 143 | // cout << "address: " << address << endl; 144 | Browser* browser = (Browser*)thisclass; 145 | 146 | // CHEAT: tam thoi cheat cho nay ko cho link vao mot so site gay crash va ads 147 | if (browser->checkBlackListAddress(address)) { 148 | return; 149 | } 150 | 151 | auto current_tab_webview = browser->get_webview_from_current_tab(); 152 | // set address bar va header title neu dang o tab do 153 | if (webview == current_tab_webview) { 154 | browser->set_title(app_name + " - " + address); 155 | browser->set_address(address); 156 | browser->check_address_bookmark(address); 157 | } 158 | 159 | // set duong dan address cho title tab vi luc nay title chua co hoac con giu title cua webview hien tai 160 | ustring tab_label_text = "↻ " + remove_http_string(address); 161 | browser->set_tab_label(webview, tab_label_text); 162 | } 163 | 164 | break; 165 | } 166 | 167 | case WEBKIT_LOAD_REDIRECTED: 168 | // cout << "WEBKIT_LOAD_REDIRECTED" << endl; 169 | break; 170 | 171 | case WEBKIT_LOAD_COMMITTED: { 172 | // cout << "WEBKIT_LOAD_COMMITTED" << endl; 173 | break; 174 | } 175 | 176 | case WEBKIT_LOAD_FINISHED: { 177 | //~ cout << "WEBKIT_LOAD_FINISHED" << endl; 178 | 179 | // phai gan gchar* cho nay vi neu de ustring crash 180 | const gchar* title = webkit_web_view_get_title(webview); 181 | const gchar* address = webkit_web_view_get_uri(webview); 182 | 183 | if (title && *title && address) { 184 | //~ cout << "title: " << title << " -- " << address << endl; 185 | Browser* browser = (Browser*)thisclass; 186 | 187 | browser->set_tab_label(webview, title); 188 | browser->save_history(title, address); 189 | } 190 | 191 | break; 192 | } 193 | } 194 | } 195 | 196 | static void webview_load_fail(WebKitWebView* webview, WebKitLoadEvent load_event, void* thisclass) { 197 | switch (load_event) { 198 | case WEBKIT_LOAD_STARTED: { 199 | // cout << "FAILED WEBKIT_LOAD_STARTED" << endl; 200 | break; 201 | } 202 | 203 | case WEBKIT_LOAD_REDIRECTED: 204 | // cout << "FAILED WEBKIT_LOAD_REDIRECTED" << endl; 205 | break; 206 | 207 | case WEBKIT_LOAD_COMMITTED: { 208 | // cout << "FAILED WEBKIT_LOAD_COMMITTED" << endl; 209 | //~ webkit_web_view_stop_loading(webview); 210 | break; 211 | } 212 | 213 | case WEBKIT_LOAD_FINISHED: { 214 | // cout << "FAILED WEBKIT_LOAD_FINISHED" << endl; 215 | //~ webkit_web_view_stop_loading(webview); 216 | break; 217 | } 218 | } 219 | } 220 | 221 | static gboolean webview_enter_fullscreen (WebKitWebView* web_view, void* thisclass) { 222 | Browser* browser = (Browser*)thisclass; 223 | browser->make_fullscreen(); 224 | return false; 225 | } 226 | 227 | static gboolean webview_leave_fullscreen (WebKitWebView* web_view, void* thisclass) { 228 | Browser* browser = (Browser*)thisclass; 229 | browser->make_unfullscreen(); 230 | return false; 231 | } 232 | 233 | void Browser::make_fullscreen() { 234 | fullscreen(); 235 | 236 | menu_box.hide(); 237 | notebook.set_show_tabs(false); 238 | browser_box_side_bar.hide(); 239 | 240 | showing_side_bar = false; 241 | is_fullscreen = true; 242 | } 243 | 244 | void Browser::make_unfullscreen() { 245 | //~ cout << "make_unfullscreen" << endl; 246 | unfullscreen(); 247 | 248 | menu_box.show(); 249 | notebook.set_show_tabs(true); 250 | 251 | is_fullscreen = false; 252 | } 253 | 254 | WebKitWebView* Browser::get_webview_from_current_tab() { 255 | int tab_index = notebook.get_current_page(); 256 | Widget* widget = notebook.get_nth_page(tab_index); 257 | WebKitWebView* webview = (WebKitWebView*)Glib::unwrap(widget); 258 | return webview; 259 | } 260 | 261 | 262 | WebKitWebContext* Browser::get_web_context(bool is_private) { 263 | 264 | if (is_private) { 265 | //~ cout << "return private " << endl; 266 | //~ return web_context_private; 267 | return web_context; // tam thoi chua xu ly 268 | } 269 | else { 270 | // tam thoi bo khong su nhieu web context 271 | //~ cout << "return context " << switch_context << endl; 272 | if (switch_context == 0) { 273 | switch_context++; 274 | return web_context; 275 | } 276 | else { 277 | switch_context = 0; 278 | //~ return web_context_second; 279 | return web_context; // tam thoi chi co 1 context 280 | } 281 | } 282 | } 283 | 284 | WebKitWebView* Browser::create_new_webview() { 285 | //~ bool is_private = false; 286 | auto web_context = get_web_context(); 287 | WebKitWebView* webview = WEBKIT_WEB_VIEW(webkit_web_view_new_with_context(web_context)); 288 | 289 | g_signal_connect(webview, "load-changed", G_CALLBACK(webview_load_change), this); 290 | g_signal_connect(webview, "load-failed", G_CALLBACK(webview_load_fail), this); 291 | g_signal_connect(webview, "create", G_CALLBACK(webview_create), this); 292 | g_signal_connect(webview, "decide-policy", G_CALLBACK(webview_decide_policy), this); 293 | g_signal_connect(webview, "enter-fullscreen", G_CALLBACK(webview_enter_fullscreen), this); 294 | g_signal_connect(webview, "leave-fullscreen", G_CALLBACK(webview_leave_fullscreen), this); 295 | 296 | return webview; 297 | } 298 | 299 | void Browser::create_new_tab(ustring address="", bool switch_to_last_tab = true) { 300 | 301 | if (notebook.get_n_pages() > LIMIT_TAB) return; 302 | set_title(app_name); // luon set header title cho app 303 | 304 | auto webview = create_new_webview(); 305 | auto widget = manage(Glib::wrap(GTK_WIDGET(webview))); 306 | notebook.append_page(*widget, "New Tab"); 307 | notebook.set_tab_reorderable(*widget, true); 308 | 309 | notebook.show_all(); 310 | if (switch_to_last_tab) 311 | jump_to_last_tab(); 312 | 313 | // load site va set address bar 314 | if (!address.empty()) { 315 | address_bar.set_text(address); 316 | webkit_web_view_load_uri(webview, address.c_str()); 317 | } 318 | 319 | // note: 320 | // Widget* widget2 = notebook.get_nth_page(0); 321 | // webview == (WebKitWebView*)Glib::unwrap(widget2) 322 | } 323 | 324 | void Browser::clone_current_tab(bool switch_to_last_tab = true) { 325 | 326 | if (notebook.get_n_pages() > LIMIT_TAB) return; 327 | 328 | auto current_webview = get_webview_from_current_tab(); 329 | auto webview = create_new_webview(); 330 | auto widget = manage(Glib::wrap(GTK_WIDGET(webview))); 331 | 332 | //~ webviews.push_back(webview); 333 | // nhu tao tab 334 | const gchar* title = webkit_web_view_get_title(current_webview); // neu ko de gtitle ma ustring, se crash 335 | if (title) { 336 | notebook.append_page(*widget, title); 337 | notebook.set_tab_reorderable(*widget, true); 338 | notebook.show_all(); 339 | set_tab_label(*widget, title); 340 | 341 | if(switch_to_last_tab) jump_to_last_tab(); 342 | } 343 | 344 | const gchar* address = webkit_web_view_get_uri(current_webview); 345 | if (address) { 346 | address_bar.set_text(address); // set lai location bar 347 | webkit_web_view_load_uri(webview, address); 348 | } 349 | } 350 | 351 | void Browser::on_search_next() { 352 | auto webview = get_webview_from_current_tab(); 353 | auto controller = webkit_web_view_get_find_controller(webview); 354 | 355 | if(webkit_find_controller_get_search_text(controller)) 356 | webkit_find_controller_search_next(controller); 357 | } 358 | 359 | void Browser::on_search_previous() { 360 | auto webview = get_webview_from_current_tab(); 361 | auto controller = webkit_web_view_get_find_controller(webview); 362 | 363 | if(webkit_find_controller_get_search_text(controller)) 364 | webkit_find_controller_search_previous(controller); 365 | } 366 | 367 | void Browser::on_search_finish() { 368 | auto webview = get_webview_from_current_tab(); 369 | auto controller = webkit_web_view_get_find_controller(webview); 370 | webkit_find_controller_search_finish(controller); 371 | } 372 | 373 | void Browser::on_search_text() { 374 | auto text = search_box_text.get_text(); 375 | if (text.empty()) return; 376 | 377 | auto webview = get_webview_from_current_tab(); 378 | auto controller = webkit_web_view_get_find_controller(webview); 379 | 380 | int match_count = 200; 381 | webkit_find_controller_search (controller, text.c_str(), WEBKIT_FIND_OPTIONS_CASE_INSENSITIVE, match_count); 382 | //WEBKIT_FIND_OPTIONS_CASE_INSENSITIVE WEBKIT_FIND_OPTIONS_NONE 383 | } 384 | 385 | /* BUTTON FUNCTION */ 386 | void Browser::on_next() { 387 | //~ cout << "on_next" << endl; 388 | 389 | // lay web hien cua tab hien tai va stop loading neu web view dang chay 390 | auto webview = get_webview_from_current_tab(); 391 | webkit_web_view_stop_loading(webview); 392 | 393 | webkit_web_view_go_forward(webview); 394 | 395 | auto title = webkit_web_view_get_title(webview); 396 | if(title) 397 | set_title(app_name + " - " + title); 398 | } 399 | 400 | void Browser::on_back() { 401 | //~ cout << "on_previous" << endl; 402 | 403 | // lay web hien cua tab hien tai va stop loading neu web view dang chay 404 | auto webview = get_webview_from_current_tab(); 405 | webkit_web_view_stop_loading(webview); 406 | 407 | webkit_web_view_go_back(webview); 408 | 409 | auto title = webkit_web_view_get_title(webview); 410 | if(title) 411 | set_title(app_name + " - " + title); 412 | } 413 | 414 | // tam thoi khong su dung 415 | bool Browser::load_search_website(ustring address, WebKitWebView* webview) { 416 | if (address == "") return false; 417 | is_none_tab = false; 418 | 419 | // thay + = %2b 420 | find_and_replace(address, "+", "%2B"); 421 | find_and_replace(address, "#", "%23"); 422 | find_and_replace(address, " ", "+"); 423 | find_and_replace(address, ":", "%3A"); 424 | 425 | // load google search 426 | ustring uri = "https://www.google.com/search?q="; 427 | //~ ustring uri = "https://www.bing.com/search?q="; 428 | uri.append(address); 429 | webkit_web_view_load_uri(webview, uri.c_str()); 430 | 431 | return true; 432 | } 433 | 434 | bool Browser::load_website(ustring address, WebKitWebView* webview) { 435 | if (address == "") return false; 436 | is_none_tab = false; 437 | 438 | // them http:// neu khong tim thay 439 | //~ if (address.find("http") == string::npos) { address = "http://" + address; } 440 | if (address.find("http") != 0) { address = "http://" + address; } 441 | webkit_web_view_load_uri(webview, address.c_str()); 442 | 443 | return true; 444 | } 445 | 446 | void Browser::on_notebook_switch_page(Gtk::Widget* widget, guint tab_index) 447 | { 448 | //~ cout << " switch to tab : " << tab_index << endl; 449 | WebKitWebView* webview = (WebKitWebView*)Glib::unwrap(widget); 450 | const gchar* title = webkit_web_view_get_title(webview); 451 | const gchar* address = webkit_web_view_get_uri(webview); 452 | 453 | if (address) { 454 | // kiem tra va hien bookmark 455 | check_address_bookmark(address); 456 | address_bar.set_text(address); 457 | } 458 | else { 459 | save_bookmark_button.set_label("♡"); 460 | address_bar.set_text(""); 461 | } 462 | 463 | if (title && *title) { 464 | //~ cout << "switch page get title: " << title << endl; 465 | set_title(app_name + " - " + title); // set lai title 466 | set_tab_label(*widget, title); 467 | } 468 | else { 469 | // title ko co thi set address thanh tab label 470 | if (address) { 471 | remove_http_string(address); 472 | set_title(app_name + " - " + address); 473 | set_tab_label(*widget, address); 474 | } 475 | } 476 | } 477 | 478 | void Browser::on_sidebook_switch_page(Gtk::Widget* widget, guint tab_index) 479 | { 480 | //~ cout << " switch to tab : " << tab_index << endl; 481 | if(tab_index == 2) { 482 | // close 483 | showing_side_bar = false; 484 | browser_box_side_bar.hide(); 485 | } 486 | } 487 | 488 | void Browser::jump_to_last_tab() { 489 | int last_tab = notebook.get_n_pages() - 1; 490 | //~ cout << "jump to tab: " << last_tab << endl; 491 | notebook.set_current_page(last_tab); 492 | address_bar.grab_focus(); // focus to address bar 493 | } 494 | 495 | void Browser::toogle_search_box() { 496 | if (showing_search_box) { 497 | search_box.hide(); 498 | showing_search_box = false; 499 | on_search_finish(); // ket thuc tim kiem 500 | } 501 | else { 502 | search_box.show(); 503 | showing_search_box = true; 504 | } 505 | } 506 | 507 | enum { HISTORY, BOOKMARK }; 508 | void Browser::toogle_side_bar(int tab_index) { 509 | if (showing_side_bar) { 510 | int current_tab = sidebook.get_current_page(); 511 | // neu dang mo tab hien tai thi dong lai 512 | if(current_tab == tab_index) { 513 | browser_box_side_bar.hide(); 514 | showing_side_bar = false; 515 | } 516 | //con neu dang mo tab khac thi switch tro lai tab_index nay 517 | else { 518 | sidebook.set_current_page(tab_index); 519 | } 520 | } 521 | else { 522 | browser_box_side_bar.show(); 523 | sidebook.set_current_page(tab_index); 524 | showing_side_bar = true; 525 | 526 | // chi rieng history moi scroll len top vi nguoi dung bao gio cung muon xem history moi nhat 527 | if (tab_index == 0) { 528 | history_tree.get_selection()->unselect_all(); // unselect tree 529 | history_scroll.get_vadjustment()->set_value(0); // scroll to top 530 | } 531 | else { 532 | // bookmark tree thi van phai unselect 533 | bookmark_tree.get_selection()->unselect_all(); // unselect tree 534 | } 535 | 536 | } 537 | 538 | // xoa bo list address da chon trong history/bookmark tree 539 | list_address_selected.clear(); 540 | } 541 | 542 | 543 | void Browser::delete_current_tab() { 544 | 545 | auto webview = get_webview_from_current_tab(); 546 | 547 | // web context 548 | auto context = get_web_context(webview); 549 | if (context == web_context) { switch_context = 0; } 550 | else { switch_context = 1; } 551 | // 552 | 553 | webkit_web_view_stop_loading(webview); // stop loading webview hien tai neu dang chay 554 | 555 | int tab_index = notebook.get_current_page(); 556 | notebook.remove_page(tab_index); 557 | //~ webviews.erase(webviews.begin()+tab_index); 558 | 559 | // khong con tab nao thi tao tab moi 560 | if(notebook.get_n_pages() == 0) { create_new_tab(); is_none_tab = true; } 561 | } 562 | 563 | bool Browser::on_key_press(GdkEventKey* event) 564 | { 565 | if(is_fullscreen) return false; 566 | 567 | switch(event->keyval) { 568 | case GDK_KEY_t: 569 | if (event->state & GDK_CONTROL_MASK ) { 570 | create_new_tab(); 571 | } 572 | break; 573 | case GDK_KEY_f: 574 | if (event->state & GDK_CONTROL_MASK) { 575 | toogle_search_box(); 576 | search_box_text.grab_focus(); 577 | } 578 | break; 579 | case GDK_KEY_w: 580 | if (event->state & GDK_CONTROL_MASK) { 581 | delete_current_tab(); 582 | } 583 | break; 584 | default: 585 | return false; 586 | } 587 | 588 | return true; 589 | } 590 | 591 | bool Browser::on_key_release(GdkEventKey* event) 592 | { 593 | //~ GdkModifierType modifiers = gtk_accelerator_get_default_mod_mask(); 594 | //~ else if((event->state & modifiers) == GDK_CONTROL_MASK) { } 595 | 596 | if (!is_fullscreen) { 597 | if (event->keyval == GDK_KEY_F2) { 598 | create_new_tab(); 599 | } 600 | // delete tab 601 | else if (event->keyval == GDK_KEY_F3) { 602 | delete_current_tab(); 603 | } 604 | else if (event->keyval == GDK_KEY_F5) { 605 | on_reload_site(); 606 | } 607 | else if (event->keyval == GDK_KEY_F6) { 608 | clone_current_tab(); 609 | } 610 | else if (event->keyval == GDK_KEY_F7) { 611 | toogle_side_bar(HISTORY); 612 | } 613 | else if (event->keyval == GDK_KEY_F8) { 614 | // open bookmark 615 | toogle_side_bar(BOOKMARK); 616 | } 617 | else if (event->keyval == GDK_KEY_Delete) { 618 | // delete history, bookmark 619 | if (history_tree.is_focus()) delete_history(); 620 | else if (bookmark_tree.is_focus()) delete_bookmark(); 621 | } 622 | } 623 | else { 624 | if (event->keyval == GDK_KEY_F11) { 625 | if (is_fullscreen) make_unfullscreen(); 626 | else make_fullscreen(); 627 | } 628 | } 629 | 630 | return true; 631 | } 632 | 633 | // press enter on entry 634 | void Browser::on_enter_address() { 635 | ustring address = address_bar.get_text(); 636 | if (address == "") return; 637 | 638 | set_title(app_name); 639 | 640 | // lay web hien cua tab hien tai va stop loading neu web view dang chay 641 | auto webview = get_webview_from_current_tab(); 642 | webkit_web_view_stop_loading(webview); // stop webview hien tai neu dang loading 643 | 644 | // check address is valid url using regex 645 | std::string regex_str = R"(^((http[s]?|ftp)://)?\/?([^/\.]+\.)*?([^/\.]+\.[^:/\s\.]{2,3}(\.[^:/\s\.]‌​{2,3})?)(:\d+)?($|/)([^#?\s]+)?(.*?)?(#[\w\-]+)?$)"; 646 | std::string regex_address = address; 647 | regex regex_url(regex_str); 648 | 649 | smatch base_match; 650 | 651 | // kiem tra day co phai la website ko 652 | if(regex_match(regex_address, base_match, regex_url)) { 653 | //~ cout << "load valid address: " << address << endl; 654 | // CHEAT: tam thoi cheat cho nay ko cho link vao mot so site gay crash va ads 655 | if (checkBlackListAddress(address)) { 656 | return; 657 | } 658 | 659 | load_website(address, webview); 660 | } 661 | // ko phai website: chuyen sang tim kiem hoac kiem tra localhost, local file 662 | else { 663 | // check day co phai la local host khong, cho phep load truc tiep 664 | if (address.find("localhost") == 0 || address.find("http://localhost") == 0 || address.find("https://localhost") == 0 665 | || address.find("127.0.0.1") == 0 || address.find("http://127.0.0.1") == 0 || address.find("https://127.0.0.1") == 0) 666 | { 667 | load_website(address, webview); // valid url 668 | } 669 | // check day co phai la local file ko 670 | else if(address.find("file://") == 0) { 671 | webkit_web_view_load_uri(webview, address.c_str()); 672 | } 673 | // check day co phai la local file ko 674 | else if(address.at(0) == '/') { 675 | string file = "file://" + address; 676 | webkit_web_view_load_uri(webview, file.c_str()); 677 | } 678 | // co khoang trang, tuc la tim kiem 679 | else if(address.find(" ") == 0) { 680 | load_search_website(address, webview); // invalid url : chuyen qua tim kiem 681 | } 682 | else { 683 | //~ cout << "search invalid address: " << address << endl; 684 | load_search_website(address, webview); // invalid url : chuyen qua tim kiem 685 | } 686 | } 687 | } 688 | 689 | void Browser::set_address(ustring name) { 690 | address_bar.set_text(""); // clear text 691 | address_bar.set_text(name); 692 | } 693 | 694 | void Browser::set_tab_label(Widget& widget, ustring name) { 695 | 696 | ustring resize_name = name; 697 | resize_name.resize(TITLE_LENGTH); 698 | 699 | //~ cout << "set tab label: " << name << endl; 700 | notebook.set_tab_label_text(widget, resize_name); 701 | } 702 | 703 | void Browser::set_tab_label(WebKitWebView* webview, ustring name) { 704 | 705 | ustring resize_name = name; 706 | resize_name.resize(TITLE_LENGTH); 707 | 708 | //~ cout << "set tab label: " << name << endl; 709 | Widget* widget = manage(Glib::wrap(GTK_WIDGET(webview))); 710 | notebook.set_tab_label_text(*widget, resize_name); 711 | } 712 | 713 | int Browser::get_current_tab() { 714 | int result = notebook.get_current_page(); 715 | if (result < 0) result = 0; 716 | return result; 717 | } 718 | 719 | /* HISTORY, BOOKMARK */ 720 | void Browser::save_history(ustring title, ustring address) { 721 | //~ cout << "save history: " << title << " - " << address << endl; 722 | // neu co history trong list thi cap nhat so lan su dung 723 | // nguoc lai insert vao database va list 724 | 725 | char* query = sqlite3_mprintf("INSERT INTO history(address, title, up) values ('%q', '%q', '%d');", 726 | address.c_str(), title.c_str(), 0); 727 | int error = run_sql(ustring(query), NULL); 728 | if (error == SQLITE_OK) { 729 | //~ cout << "insert history success " << address << endl; 730 | 731 | // them address vao list 732 | load_history(title, address); 733 | 734 | // them vao history tree 735 | add_history_tree(title, address, true); 736 | 737 | add_address_store(title, address); // them vao address store de search khi go text 738 | } 739 | else { 740 | add_history_tree(title, address, true); // them len top khoi can xoa trong tree 741 | 742 | // cap nhat so lan su dung va title lan nua, tam thoi chua can su dung 743 | //~ query = sqlite3_mprintf( "UPDATE history SET up = up + 1, title='%q' WHERE address = '%q' ;", title.c_str(), address.c_str()); 744 | //~ error = run_sql(ustring(query), NULL); 745 | //~ if (error == SQLITE_OK) { 746 | //~ // cout << "update success history " << endl; 747 | //~ } 748 | 749 | //~ // cap nhat lai history tree 750 | //~ auto children = history_store->children(); 751 | //~ for(auto& iter : children) { 752 | //~ auto row = *iter; 753 | //~ if(row[tree_model.column_address] == address) { 754 | 755 | //~ history_store->erase(iter); // remove khoi dong hien tai 756 | //~ add_history_tree(title, address); // them len top 757 | //~ break; 758 | //~ } 759 | //~ } 760 | } 761 | } 762 | 763 | void Browser::save_bookmark(ustring title, ustring address) { 764 | if (title.empty() && address.empty()) return; 765 | 766 | //~ cout << "save book: " << title << " - " << address << endl; 767 | // save to db 768 | 769 | // insert address 770 | char* query = sqlite3_mprintf("INSERT INTO bookmark(address, title) values ('%q', '%q');", 771 | address.c_str(), title.c_str()); 772 | int error = run_sql(ustring(query), NULL); 773 | 774 | sqlite3_free(query); 775 | 776 | // insert thanh cong 777 | if (error == SQLITE_OK) { 778 | // add to list 779 | //~ tuple tmp(title, address); 780 | //~ list_bookmark.push_front(tmp); 781 | // std::map, address lam key chinh nen add address truoc 782 | list_bookmark.insert(std::pair(address, title)); 783 | 784 | // them vao bookmark tree 785 | add_bookmark_tree(title, address, true); 786 | save_bookmark_button.set_label("♥"); 787 | 788 | add_address_store(title, address); // them vao address store de search khi go text 789 | } 790 | } 791 | 792 | void Browser::on_save_bookmark() { 793 | 794 | int tab_index = notebook.get_current_page(); 795 | Widget* widget = notebook.get_nth_page(tab_index); 796 | WebKitWebView* webview = (WebKitWebView*)Glib::unwrap(widget); 797 | 798 | const gchar* title = webkit_web_view_get_title(webview); 799 | const gchar* address = webkit_web_view_get_uri(webview); 800 | 801 | if (title && address) { 802 | save_bookmark(title, address); 803 | } 804 | } 805 | 806 | void Browser::on_show_bookmark() { 807 | toogle_side_bar(BOOKMARK); 808 | } 809 | 810 | void Browser::check_address_bookmark(ustring address) { 811 | if (address.empty()) { 812 | save_bookmark_button.set_label("♡"); 813 | return; 814 | } 815 | 816 | //~ cout << "check address bookmark" << address << endl; 817 | //~ for(auto& x: list_bookmark) { 818 | //~ ustring tuple_address = get<1>(x); 819 | //~ if (address == tuple_address) { 820 | //~ // cout << "we bookmarked this address " << address << endl; 821 | //~ save_bookmark_button.set_label("♥"); 822 | //~ return; 823 | //~ } 824 | //~ } 825 | 826 | for(auto it = list_bookmark.cbegin(); it != list_bookmark.cend();) { 827 | if (it->first.compare(address) == 0) { 828 | save_bookmark_button.set_label("♥"); 829 | return; 830 | } 831 | else 832 | ++it; 833 | } 834 | 835 | //~ cout << "still not bookmark: " << address << endl; 836 | save_bookmark_button.set_label("♡"); 837 | } 838 | void Browser::on_show_history() { 839 | toogle_side_bar(HISTORY); 840 | } 841 | 842 | /* DB */ 843 | void Browser::load_history(ustring title, ustring address) { 844 | //~ tuple tmp(title, address); 845 | //~ list_history.push_front(tmp); 846 | } 847 | 848 | void Browser::load_bookmark(ustring title, ustring address) { 849 | list_bookmark.insert(std::pair(address, title)); 850 | } 851 | 852 | void Browser::add_history_tree(ustring title, ustring address, bool prepend = false) { 853 | TreeModel::iterator iter; 854 | if(prepend) iter = history_store->prepend(); 855 | else iter = history_store->append(); 856 | 857 | TreeModel::Row row = *iter; 858 | row[tree_model.column_title] = title; 859 | row[tree_model.column_address] = address; 860 | } 861 | 862 | void Browser::add_bookmark_tree(ustring title, ustring address, bool prepend = false) { 863 | //~ TreeModel::iterator iter = bookmark_store->append(); 864 | TreeModel::iterator iter; 865 | if(prepend) iter = bookmark_store->prepend(); 866 | else iter = bookmark_store->append(); 867 | 868 | TreeModel::Row row = *iter; 869 | row[tree_model.column_title] = title; 870 | row[tree_model.column_address] = address; 871 | } 872 | 873 | void Browser::add_address_store(ustring title, ustring address) { 874 | //~ cout << " add addresss store : " << title << " - " << address << endl; 875 | //~ TreeModel::iterator iter = address_store->prepend(); 876 | //~ TreeModel::Row row = *iter; 877 | //~ row[address_model_column.column_name] = title; 878 | 879 | //~ iter = address_store->prepend(row.children()); 880 | //~ TreeModel::Row childrow = *iter; 881 | //~ childrow[address_model_column.column_name] = address; 882 | 883 | //~ TreeModel::iterator iter = address_store->prepend(); 884 | //~ TreeModel::Row row = *iter; 885 | //~ row[address_model_column.column_name] = title; 886 | //~ row[address_model_column.column_address] = address; 887 | } 888 | 889 | static int load_all_bookmark(void* thisclass, int argc, char** argv, char** col) { 890 | Browser* browser = (Browser*)thisclass; 891 | ustring title, address; 892 | 893 | // iterator through all data, index = 0: address, index = 1: title 894 | for(int i = 0; i < argc; i++) { 895 | if (i == 0) address = ustring(argv[i]); 896 | else if (i == 1) title = ustring(argv[i]); 897 | } 898 | 899 | // them vao danh sach bookmark de su dung 900 | if (title != "" && address != "") { 901 | // cout << "load history: " << title << " ::: " << address << endl; 902 | browser->load_bookmark(title, address); 903 | browser->add_bookmark_tree(title, address); 904 | 905 | browser->add_address_store(title, address); // them vao address store de search khi go text 906 | } 907 | 908 | return 0; 909 | } 910 | 911 | static int load_all_history(void* thisclass, int argc, char** argv, char** col) { 912 | 913 | Browser* browser = (Browser*)thisclass; 914 | ustring title, address; 915 | 916 | // iterator through all data, index = 0: address, index = 1: title 917 | for(int i = 0; i < argc; i++) { 918 | if (i == 0) address = ustring(argv[i]); 919 | else if (i == 1) title = ustring(argv[i]); 920 | } 921 | 922 | // them vao danh sach history de su dung 923 | if (title != "" && address != "") { 924 | // cout << "load history: " << title << " ::: " << address << endl; 925 | browser->load_history(title, address); 926 | browser->add_history_tree(title, address); 927 | 928 | browser->add_address_store(title, address); // them vao address store de search khi go text 929 | } 930 | 931 | return 0; 932 | } 933 | 934 | int Browser::run_sql(ustring sql, int(*func)(void*, int, char**, char**)) { 935 | ustring db_path = exe_path + "/data.db"; 936 | 937 | sqlite3 *db; 938 | int error = sqlite3_open(db_path.c_str(), &db); 939 | if (error) { 940 | //~ cout << "Can't open database: " << sqlite3_errmsg(db) << endl; 941 | sqlite3_close(db); 942 | return error; 943 | } 944 | 945 | char* errmsg = 0; 946 | error = sqlite3_exec(db, sql.c_str(), func, this, &errmsg); 947 | if (error != SQLITE_OK) { 948 | //~ cout << "SQL Error: " << errmsg << endl; 949 | sqlite3_free(errmsg); 950 | } 951 | sqlite3_close(db); 952 | return error; 953 | } 954 | 955 | void Browser::on_bookmark_tree_double_click(const TreeModel::Path& path, TreeViewColumn* column) { 956 | TreeModel::iterator iter = bookmark_store->get_iter(path); 957 | if (iter) { 958 | TreeModel::Row row = *iter; 959 | ustring address = row[tree_model.column_address]; 960 | 961 | // neu chi moi chi co 1 tab thi load len tab do luon 962 | if (is_none_tab) { 963 | is_none_tab = false; 964 | 965 | if(address.find("file://") == 0) { 966 | webkit_web_view_load_uri(get_webview_from_current_tab(), address.c_str()); 967 | } 968 | // check day co phai la local file ko 969 | else if(address.at(0) == '/') { 970 | string file = "file://" + address; 971 | webkit_web_view_load_uri(get_webview_from_current_tab(), file.c_str()); 972 | } 973 | else { 974 | load_website(address, get_webview_from_current_tab()); 975 | } 976 | } 977 | else create_new_tab(address); 978 | } 979 | } 980 | 981 | void Browser::on_history_tree_double_click(const TreeModel::Path& path, TreeViewColumn* column) { 982 | TreeModel::iterator iter = history_store->get_iter(path); 983 | if (iter) { 984 | TreeModel::Row row = *iter; 985 | ustring address = row[tree_model.column_address]; 986 | 987 | // neu chi moi chi co 1 tab thi load len tab do luon 988 | if (is_none_tab) { 989 | is_none_tab = false; 990 | 991 | if(address.find("file://") == 0) { 992 | webkit_web_view_load_uri(get_webview_from_current_tab(), address.c_str()); 993 | } 994 | // check day co phai la local file ko 995 | else if(address.at(0) == '/') { 996 | string file = "file://" + address; 997 | webkit_web_view_load_uri(get_webview_from_current_tab(), file.c_str()); 998 | } 999 | else { 1000 | load_website(address, get_webview_from_current_tab()); 1001 | } 1002 | } 1003 | else create_new_tab(address); 1004 | } 1005 | } 1006 | 1007 | void Browser::on_reload_site() { 1008 | auto webview = get_webview_from_current_tab(); 1009 | webkit_web_view_stop_loading(webview); // stop loading webview hien tai neu dang chay 1010 | webkit_web_view_reload(webview); // reload 1011 | } 1012 | 1013 | void Browser::on_completion_action_activated(int index) { 1014 | //~ cout << "clicked ===========" << endl; 1015 | action_map::iterator iter = completion_action.find(index); 1016 | if(iter != completion_action.end()) { 1017 | Glib::ustring title = iter->second; 1018 | //~ cout << "Action selected: " << title << std::endl; 1019 | } 1020 | } 1021 | 1022 | bool Browser::on_completion_match(const Glib::ustring& key, const Gtk::TreeModel::const_iterator& iter) { 1023 | if(iter) { 1024 | 1025 | Glib::ustring::size_type key_length = key.size(); 1026 | if (key_length <= 1) return false; // khong search text chi co 1 chu hoac khong 1027 | 1028 | Gtk::TreeModel::Row row = *iter; 1029 | Glib::ustring filter_string = row[address_model_column.column_name]; 1030 | 1031 | Glib::ustring filter_string_start = filter_string.substr(0, key_length); 1032 | filter_string_start = filter_string_start.lowercase(); // lower case de tim kiem duoc nhieu hon 1033 | 1034 | if(key == filter_string_start) { 1035 | //~ Glib::ustring address = row[address_model_column.column_address]; 1036 | return true; //A match was found. 1037 | } 1038 | } 1039 | 1040 | return false; //No match. 1041 | } 1042 | 1043 | void Browser::delete_history() { 1044 | 1045 | if (list_address_selected.size() <= 0) return; 1046 | 1047 | // xoa trong tree 1048 | auto model = history_tree.get_model(); 1049 | auto paths = history_tree.get_selection()->get_selected_rows(); 1050 | 1051 | // xoa nguoc tu duoi len tren, vi history store se bi loi khi xoa tu tren xuong => ko tim duoc dong tiep theo 1052 | while(!paths.empty()) { 1053 | auto path = paths.back(); 1054 | auto iter = model->get_iter(path); 1055 | history_store->erase(iter); 1056 | paths.pop_back(); // remove last element from paths; 1057 | } 1058 | history_tree.get_selection()->unselect_all(); 1059 | history_scroll.get_vadjustment()->set_value(0); // scroll to top 1060 | 1061 | // remove duplicate element, sort first 1062 | sort(list_address_selected.begin(), list_address_selected.end()); 1063 | list_address_selected.erase(unique(list_address_selected.begin(), list_address_selected.end() ), list_address_selected.end()); 1064 | 1065 | // xoa trong csdl 1066 | string sql = "DELETE FROM history WHERE address IN ("; 1067 | for(auto& x : list_address_selected) { 1068 | sql.append("'"); 1069 | sql.append(x.c_str()); 1070 | sql.append("',"); 1071 | } 1072 | sql.pop_back(); 1073 | sql.append(");"); 1074 | run_sql(sql, NULL); 1075 | } 1076 | 1077 | void Browser::delete_bookmark() { 1078 | if (list_address_selected.size() <= 0) return; 1079 | 1080 | // xoa trong tree 1081 | auto model = bookmark_tree.get_model(); 1082 | auto paths = bookmark_tree.get_selection()->get_selected_rows(); 1083 | 1084 | while(!paths.empty()) { 1085 | auto path = paths.back(); 1086 | auto iter = model->get_iter(path); 1087 | bookmark_store->erase(iter); 1088 | paths.pop_back(); // remove last element from paths; 1089 | } 1090 | bookmark_tree.get_selection()->unselect_all(); 1091 | 1092 | // delete bookmark ko can scroll to top 1093 | //~ bookmark_scroll.get_vadjustment()->set_value(0); // scroll to top 1094 | 1095 | // bookmark is unique, ko can remove duplicate 1096 | //~ // remove duplicate element, sort first 1097 | //~ sort(list_address_selected.begin(), list_address_selected.end()); 1098 | //~ list_address_selected.erase(unique(list_address_selected.begin(), list_address_selected.end() ), list_address_selected.end()); 1099 | 1100 | // xoa trong csdl 1101 | string sql = "DELETE FROM bookmark WHERE address IN ("; 1102 | for(auto& x : list_address_selected) { 1103 | sql.append("'"); 1104 | sql.append(x.c_str()); 1105 | sql.append("',"); 1106 | } 1107 | sql.pop_back(); 1108 | sql.append(");"); 1109 | run_sql(sql, NULL); 1110 | 1111 | // delete from list bookmark 1112 | for(auto it = list_bookmark.begin(); it != list_bookmark.end();) { 1113 | for(auto& x : list_address_selected) { 1114 | if (it->first.compare(x) == 0) 1115 | it = list_bookmark.erase(it); 1116 | else 1117 | ++it; 1118 | } 1119 | } 1120 | 1121 | // remove bookmark symbol tab hien tai neu co 1122 | auto webview = get_webview_from_current_tab(); 1123 | auto address = webkit_web_view_get_uri(webview); 1124 | if (address) check_address_bookmark(address); 1125 | 1126 | // xoa trong csdl 1127 | //~ for(auto& x : list_address_selected) { 1128 | //~ // cout << "delete: " << x << endl; 1129 | //~ char* query = sqlite3_mprintf("DELETE FROM bookmark WHERE address = '%q' ;", x.c_str()); 1130 | //~ int error = run_sql(ustring(query), NULL); 1131 | 1132 | //~ sqlite3_free(query); 1133 | //~ } 1134 | } 1135 | 1136 | void Browser::on_history_tree_focus() 1137 | { 1138 | list_address_selected.clear(); // clear select paths before for each 1139 | history_tree.get_selection()->selected_foreach_iter(sigc::mem_fun(*this, &Browser::on_history_tree_selected)); 1140 | } 1141 | 1142 | void Browser::on_bookmark_tree_focus() 1143 | { 1144 | list_address_selected.clear(); // clear select paths before for each 1145 | bookmark_tree.get_selection()->selected_foreach_iter(sigc::mem_fun(*this, &Browser::on_bookmark_tree_selected)); 1146 | } 1147 | 1148 | void Browser::on_history_tree_selected(const TreeModel::iterator& iter) { 1149 | TreeModel::Row row = *iter; 1150 | list_address_selected.push_back(row[tree_model.column_address]); 1151 | } 1152 | 1153 | void Browser::on_bookmark_tree_selected(const TreeModel::iterator& iter) { 1154 | TreeModel::Row row = *iter; 1155 | list_address_selected.push_back(row[tree_model.column_address]); 1156 | } 1157 | 1158 | Browser::Browser(ustring path) 1159 | : exe_path(path), blacklist(path) 1160 | { 1161 | /* WINDOW */ 1162 | set_title("DBT Browser"); 1163 | set_border_width(0); 1164 | set_default_size(1024, 600); 1165 | 1166 | maximize(); 1167 | 1168 | add(main_box); 1169 | main_box.pack_start(menu_box, PACK_SHRINK); 1170 | main_box.pack_start(browser_box, PACK_EXPAND_WIDGET); 1171 | main_box.pack_start(search_box, PACK_SHRINK, 2); 1172 | 1173 | menu_box.pack_start(back_button, PACK_SHRINK); 1174 | menu_box.pack_start(next_button, PACK_SHRINK); 1175 | menu_box.pack_start(address_bar, PACK_EXPAND_WIDGET); 1176 | menu_box.pack_start(reload_button, PACK_SHRINK); 1177 | menu_box.pack_start(save_bookmark_button, PACK_SHRINK); 1178 | menu_box.pack_start(history_button, PACK_SHRINK); 1179 | menu_box.pack_start(bookmark_button, PACK_SHRINK); 1180 | 1181 | browser_box.pack_start(browser_box_side_bar, PACK_SHRINK); 1182 | browser_box.pack_start(notebook, PACK_EXPAND_WIDGET); 1183 | 1184 | search_box.pack_end(search_box_close_button, PACK_SHRINK, 16); 1185 | search_box.pack_end(search_box_matches, PACK_SHRINK, 12); 1186 | search_box.pack_end(search_box_highlight_button, PACK_SHRINK, 12); 1187 | search_box.pack_end(search_box_down_button, PACK_SHRINK); 1188 | search_box.pack_end(search_box_up_button, PACK_SHRINK); 1189 | search_box.pack_end(search_box_text, PACK_SHRINK); 1190 | search_box.pack_end(search_title, PACK_SHRINK, 8); 1191 | 1192 | //~ search_box.pack_start(search_box_close_button, PACK_SHRINK, 8); 1193 | //~ search_box.pack_start(search_box_text, PACK_SHRINK); 1194 | //~ search_box.pack_start(search_box_up_button, PACK_SHRINK); 1195 | //~ search_box.pack_start(search_box_down_button, PACK_SHRINK); 1196 | //~ search_box.pack_start(search_box_highlight_button, PACK_SHRINK, 8); 1197 | //~ search_box.pack_start(search_box_matches, PACK_SHRINK, 8); 1198 | 1199 | browser_box_side_bar.pack_start(sidebook, PACK_EXPAND_WIDGET); 1200 | 1201 | // search box 1202 | //~ search_box.set_border_width(2); 1203 | search_title.set_text("Search: "); 1204 | search_box_up_button.set_label("▲"); 1205 | search_box_down_button.set_label("▼"); 1206 | search_box_highlight_button.set_label("Hightlight"); 1207 | search_box_matches.set_text("Matches"); 1208 | search_box_close_button.set_label("✖"); 1209 | 1210 | // scroll bar; 1211 | history_scroll.add(history_tree); 1212 | bookmark_scroll.add(bookmark_tree); 1213 | 1214 | sidebook.append_page(history_scroll, "History"); 1215 | sidebook.append_page(bookmark_scroll, "Bookmark"); 1216 | sidebook.set_tab_reorderable(history_scroll, true); 1217 | sidebook.set_tab_reorderable(bookmark_scroll, true); 1218 | sidebook.append_page(close_side_bar, "x"); 1219 | 1220 | /* MENU BUTTON */ 1221 | back_button.set_label("◁"); 1222 | next_button.set_label("▷"); 1223 | save_bookmark_button.set_label("♡"); 1224 | history_button.set_label("History"); 1225 | bookmark_button.set_label("Bookmark"); 1226 | reload_button.set_label("↻"); 1227 | 1228 | /* NOTE BOOK */ 1229 | notebook.set_scrollable(true); 1230 | 1231 | /* SIDE BOOK */ 1232 | sidebook.set_scrollable(true); 1233 | sidebook.set_size_request(360, -1); 1234 | 1235 | /* HISTORY, BOOKMARK TREE */ 1236 | history_scroll.set_border_width(4); 1237 | history_scroll.set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC); 1238 | 1239 | bookmark_scroll.set_border_width(4); 1240 | bookmark_scroll.set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC); 1241 | 1242 | history_store = ListStore::create(tree_model); 1243 | history_tree.set_model(history_store); 1244 | history_tree.append_column("Title", tree_model.column_title); 1245 | history_tree.append_column("Address", tree_model.column_address); 1246 | history_tree.set_headers_visible(false); 1247 | history_tree.get_column(0)->set_min_width(160); 1248 | history_tree.get_column(0)->set_max_width(480); 1249 | 1250 | bookmark_store = ListStore::create(tree_model); 1251 | bookmark_tree.set_model(bookmark_store); 1252 | bookmark_tree.append_column("Title", tree_model.column_title); 1253 | bookmark_tree.append_column("Address", tree_model.column_address); 1254 | bookmark_tree.set_headers_visible(false); 1255 | bookmark_tree.get_column(0)->set_min_width(160); 1256 | bookmark_tree.get_column(0)->set_max_width(480); 1257 | 1258 | /* CONNECT FUNCTION */ 1259 | next_button.signal_clicked().connect(sigc::mem_fun(*this, &Browser::on_next)); 1260 | back_button.signal_clicked().connect(sigc::mem_fun(*this, &Browser::on_back)); 1261 | save_bookmark_button.signal_clicked().connect(sigc::mem_fun(*this, &Browser::on_save_bookmark)); 1262 | history_button.signal_clicked().connect(sigc::mem_fun(*this, &Browser::on_show_history)); 1263 | bookmark_button.signal_clicked().connect(sigc::mem_fun(*this, &Browser::on_show_bookmark)); 1264 | reload_button.signal_clicked().connect(sigc::mem_fun(*this, &Browser::on_reload_site)); 1265 | 1266 | address_bar.signal_activate().connect(sigc::mem_fun(*this, &Browser::on_enter_address)); 1267 | notebook.signal_switch_page().connect(sigc::mem_fun(*this, &Browser::on_notebook_switch_page)); 1268 | sidebook.signal_switch_page().connect(sigc::mem_fun(*this, &Browser::on_sidebook_switch_page)); 1269 | 1270 | history_tree.signal_row_activated().connect(sigc::mem_fun(*this, &Browser::on_history_tree_double_click)); 1271 | history_tree.get_selection()->set_mode(Gtk::SELECTION_MULTIPLE); 1272 | history_tree.signal_grab_focus().connect(sigc::mem_fun(*this, &Browser::on_history_tree_focus)); 1273 | 1274 | bookmark_tree.signal_row_activated().connect(sigc::mem_fun(*this, &Browser::on_bookmark_tree_double_click)); 1275 | bookmark_tree.get_selection()->set_mode(Gtk::SELECTION_MULTIPLE); 1276 | bookmark_tree.signal_grab_focus().connect(sigc::mem_fun(*this, &Browser::on_bookmark_tree_focus)); 1277 | 1278 | search_box_down_button.signal_clicked().connect(sigc::mem_fun(*this, &Browser::on_search_next)); 1279 | search_box_up_button.signal_clicked().connect(sigc::mem_fun(*this, &Browser::on_search_previous)); 1280 | search_box_text.signal_activate().connect(sigc::mem_fun(*this, &Browser::on_search_text)); 1281 | search_box_close_button.signal_clicked().connect(sigc::mem_fun(*this, &Browser::toogle_search_box)); 1282 | 1283 | this->add_events( Gdk::KEY_PRESS_MASK); 1284 | this->signal_key_release_event().connect(sigc::mem_fun(*this, &Browser::on_key_release)); 1285 | this->signal_key_press_event().connect(sigc::mem_fun(*this, &Browser::on_key_press)); 1286 | 1287 | show_all_children(); 1288 | 1289 | web_data_manager = webkit_website_data_manager_new((exe_path + "/data/data_base").c_str(), (exe_path + "/data/data_cache").c_str(), 1290 | (exe_path + "/data/local_storage").c_str(), (exe_path + "/data/disk_cache").c_str(), (exe_path + "/data/offline_cache").c_str(), 1291 | (exe_path + "/data/index").c_str(), (exe_path + "/data/websql").c_str()); 1292 | 1293 | /* WEBKIT */ 1294 | //~ WEBKIT_CACHE_MODEL_DOCUMENT_VIEWER 1295 | //~ WEBKIT_CACHE_MODEL_DOCUMENT_BROWSER 1296 | //~ WEBKIT_CACHE_MODEL_WEB_BROWSER 1297 | 1298 | //~ WEBKIT_PROCESS_MODEL_SHARED_SECONDARY_PROCESS 1299 | //~ WEBKIT_PROCESS_MODEL_MULTIPLE_SECONDARY_PROCESSES 1300 | 1301 | //~ WEBKIT_TLS_ERRORS_POLICY_IGNORE 1302 | //~ WEBKIT_TLS_ERRORS_POLICY_FAIL 1303 | 1304 | // context 1 1305 | web_context = webkit_web_context_new_with_website_data_manager(web_data_manager); 1306 | webkit_web_context_set_cache_model(web_context, WEBKIT_CACHE_MODEL_WEB_BROWSER); 1307 | webkit_web_context_set_process_model(web_context, WEBKIT_PROCESS_MODEL_MULTIPLE_SECONDARY_PROCESSES); 1308 | webkit_web_context_set_web_process_count_limit(web_context, LIMIT_TAB); 1309 | //~ webkit_web_context_set_tls_errors_policy(web_context, WEBKIT_TLS_ERRORS_POLICY_FAIL); 1310 | 1311 | // context 2 1312 | //~ web_context_second = webkit_web_context_new_with_website_data_manager(web_data_manager); 1313 | //~ webkit_web_context_set_cache_model(web_context_second, WEBKIT_CACHE_MODEL_WEB_BROWSER); 1314 | //~ webkit_web_context_set_process_model(web_context_second, WEBKIT_PROCESS_MODEL_MULTIPLE_SECONDARY_PROCESSES); 1315 | //~ webkit_web_context_set_web_process_count_limit(web_context_second, LIMIT_TAB); 1316 | //~ webkit_web_context_set_tls_errors_policy(web_context_second, WEBKIT_TLS_ERRORS_POLICY_FAIL); 1317 | 1318 | // private context 1319 | //~ web_context_private = webkit_web_context_new_with_website_data_manager(web_data_manager); 1320 | //~ webkit_web_context_set_cache_model(web_context_private, WEBKIT_CACHE_MODEL_WEB_BROWSER); 1321 | //~ webkit_web_context_set_process_model(web_context_private, WEBKIT_PROCESS_MODEL_SHARED_SECONDARY_PROCESS); 1322 | //~ webkit_web_context_set_web_process_count_limit(web_context_private, LIMIT_TAB); 1323 | //~ webkit_web_context_set_tls_errors_policy(web_context_private, WEBKIT_TLS_ERRORS_POLICY_FAIL); 1324 | 1325 | // varible 1326 | switch_context = 0; 1327 | is_fullscreen = false; 1328 | is_none_tab = true; 1329 | 1330 | // cookie manager 1331 | //~ WEBKIT_COOKIE_POLICY_ACCEPT_ALWAYS 1332 | //~ WEBKIT_COOKIE_POLICY_ACCEPT_NEVER 1333 | //~ WEBKIT_COOKIE_POLICY_ACCEPT_NO_THIRD_PARTY 1334 | 1335 | //~ WEBKIT_COOKIE_PERSISTENT_STORAGE_TEXT 1336 | //~ WEBKIT_COOKIE_PERSISTENT_STORAGE_SQLITE 1337 | 1338 | // cookie 1 1339 | auto cookie_path = exe_path + "/cookie"; 1340 | auto cookie_manager = webkit_web_context_get_cookie_manager (web_context); 1341 | webkit_cookie_manager_set_accept_policy(cookie_manager, WEBKIT_COOKIE_POLICY_ACCEPT_ALWAYS); 1342 | webkit_cookie_manager_set_persistent_storage(cookie_manager, cookie_path.c_str(), WEBKIT_COOKIE_PERSISTENT_STORAGE_TEXT); 1343 | 1344 | //~ // cookie 2 1345 | //~ cookie_manager = webkit_web_context_get_cookie_manager(web_context_second); 1346 | //~ webkit_cookie_manager_set_accept_policy(cookie_manager, WEBKIT_COOKIE_POLICY_ACCEPT_ALWAYS); 1347 | //~ webkit_cookie_manager_set_persistent_storage(cookie_manager, cookie_path.c_str(), WEBKIT_COOKIE_PERSISTENT_STORAGE_SQLITE); 1348 | 1349 | //~ // private cookie 1350 | //~ cookie_manager = webkit_web_context_get_cookie_manager(web_context_private); 1351 | //~ webkit_cookie_manager_set_accept_policy(cookie_manager, WEBKIT_COOKIE_POLICY_ACCEPT_NEVER); 1352 | 1353 | create_new_tab(); 1354 | 1355 | /* SIDE BAR */ 1356 | browser_box_side_bar.hide(); 1357 | showing_side_bar = false; 1358 | 1359 | /* SEARCH BOX */ 1360 | search_box.hide(); 1361 | showing_search_box = false; 1362 | 1363 | /* CLIPBOARD */ 1364 | 1365 | /* ENTRY COMPLETION */ 1366 | address_completion = EntryCompletion::create(); 1367 | address_bar.set_completion(address_completion); 1368 | 1369 | address_store = TreeStore::create(address_model_column); 1370 | address_completion->set_model(address_store); 1371 | address_completion->set_text_column(address_model_column.column_address); 1372 | 1373 | // tam thoi bo qua 1374 | //~ address_completion->signal_action_activated().connect( sigc::mem_fun(*this, &Browser::on_completion_action_activated)); 1375 | //~ address_completion->set_match_func(sigc::mem_fun(*this, &Browser::on_completion_match)); 1376 | 1377 | //~ completion_action[0] = "Use Wizard"; 1378 | //~ const auto& the_pair : completion_action 1379 | //~ auto position = the_pair.first; 1380 | //~ auto title = the_pair.second; 1381 | //~ completion->insert_action_text(title, position); 1382 | 1383 | /* DB */ 1384 | run_sql("select * from bookmark order by datetime(time) DESC", load_all_bookmark); 1385 | run_sql("select * from history order by datetime(time) DESC", load_all_history); 1386 | } 1387 | 1388 | -------------------------------------------------------------------------------- /browser.h: -------------------------------------------------------------------------------- 1 | #ifndef BROWSER_H 2 | #define BROWSER_H 3 | 4 | #include "header.h" 5 | #include "webview.h" 6 | #include "model.h" 7 | #include "blacklist.h" 8 | #include 9 | 10 | class Browser : public Window { 11 | public: 12 | Browser(ustring path); 13 | ~Browser(); 14 | 15 | void on_notebook_switch_page(Gtk::Widget*, guint); 16 | void on_sidebook_switch_page(Gtk::Widget*, guint); 17 | 18 | bool load_website(ustring, WebKitWebView*); 19 | bool load_search_website(ustring, WebKitWebView*); 20 | 21 | bool on_key_press(GdkEventKey*); 22 | bool on_key_release(GdkEventKey*); 23 | 24 | void on_enter_address(); 25 | void set_address(ustring); 26 | void set_tab_label(Widget&, ustring); 27 | void set_tab_label(WebKitWebView*, ustring); 28 | 29 | void create_new_tab(ustring,bool); 30 | void clone_current_tab(bool); 31 | void delete_current_tab(); 32 | 33 | int get_current_tab(); 34 | void jump_to_last_tab(); 35 | 36 | void on_back(); 37 | void on_next(); 38 | 39 | void check_address_bookmark(ustring); 40 | void on_save_bookmark(); 41 | 42 | void on_show_history(); 43 | void on_show_bookmark(); 44 | 45 | void save_history(ustring, ustring); 46 | void save_bookmark(ustring, ustring); 47 | 48 | void load_history(ustring, ustring); 49 | void load_bookmark(ustring, ustring); 50 | 51 | void add_bookmark_tree(ustring, ustring, bool); 52 | void add_history_tree(ustring, ustring, bool); 53 | 54 | void on_history_tree_focus(); 55 | void on_bookmark_tree_focus(); 56 | 57 | void on_history_tree_selected(const TreeModel::iterator&); 58 | void on_bookmark_tree_selected(const TreeModel::iterator&); 59 | 60 | Notebook& get_notebook() { return notebook; } 61 | void toogle_side_bar(int); 62 | 63 | int run_sql(ustring, int(*func)(void*, int, char**, char**)); 64 | 65 | void on_bookmark_tree_double_click(const TreeModel::Path&, TreeViewColumn*); 66 | void on_history_tree_double_click(const TreeModel::Path&, TreeViewColumn*); 67 | 68 | void toogle_search_box(); 69 | 70 | WebKitWebView* create_new_webview(); 71 | void make_fullscreen(); 72 | void make_unfullscreen(); 73 | 74 | WebKitWebView* get_webview_from_current_tab(); 75 | 76 | void on_search_text(); 77 | void on_search_next(); 78 | void on_search_previous(); 79 | void on_search_finish(); 80 | 81 | void on_reload_site(); 82 | 83 | void add_address_store(ustring, ustring); 84 | 85 | WebKitWebContext* get_web_context(bool is_private = false); 86 | 87 | void delete_history(); 88 | void delete_bookmark(); 89 | 90 | bool checkBlackListAddress(std::string); 91 | 92 | protected: 93 | 94 | ustring exe_path; 95 | bool is_fullscreen; 96 | bool is_none_tab; 97 | 98 | VBox main_box; 99 | HBox menu_box; 100 | HBox browser_box; 101 | HBox search_box; 102 | 103 | VBox browser_box_side_bar; 104 | 105 | TreeView history_tree; 106 | TreeView bookmark_tree; 107 | Glib::RefPtr history_store; 108 | Glib::RefPtr bookmark_store; 109 | ModelColumns tree_model; 110 | 111 | ScrolledWindow bookmark_scroll; 112 | ScrolledWindow history_scroll; 113 | 114 | Entry address_bar; 115 | Notebook notebook; 116 | Notebook sidebook; 117 | 118 | Button back_button; 119 | Button next_button; 120 | Button history_button; 121 | Button bookmark_button; 122 | Button save_bookmark_button; 123 | Button reload_button; 124 | 125 | Label close_side_bar; 126 | bool showing_side_bar; 127 | 128 | /* search box */ 129 | Label search_title; 130 | Entry search_box_text; 131 | Button search_box_up_button; 132 | Button search_box_down_button; 133 | Button search_box_highlight_button; 134 | Label search_box_matches; 135 | Button search_box_close_button; 136 | bool showing_search_box; 137 | 138 | vector webviews; 139 | WebKitWebsiteDataManager* web_data_manager; 140 | WebKitWebContext* web_context; 141 | //~ WebKitWebContext* web_context_second; 142 | //~ WebKitWebContext* web_context_private; 143 | int switch_context; 144 | //~ vector list_context; 145 | 146 | // history, bookmark 147 | deque> list_history; 148 | //~ deque> list_bookmark; 149 | std::map list_bookmark; 150 | vector list_address_selected; 151 | 152 | //~ Clipboard clipboard; 153 | //~ c = Gtk.Clipboard.get(Gdk.SELECTION_PRIMARY) 154 | //~ print c.wait_for_text() 155 | 156 | // entry completetion 157 | void on_completion_action_activated(int index); 158 | bool on_completion_match(const Glib::ustring& key, const Gtk::TreeModel::const_iterator& iter); 159 | 160 | typedef std::map action_map; 161 | action_map completion_action; 162 | Glib::RefPtr address_store; 163 | 164 | Glib::RefPtr address_completion; 165 | AddressModelColumn address_model_column; 166 | 167 | BlackList blacklist; 168 | }; 169 | 170 | // icon: ♡ ♥ ❤ ▲ ▼ ✖ ↻ 171 | // PACK_SHRINK, PACK_EXPAND_WIDGET, PACK_EXPAND_PADDING 172 | #endif 173 | -------------------------------------------------------------------------------- /header.h: -------------------------------------------------------------------------------- 1 | #ifndef HEADER_H 2 | #define HEADER_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | namespace fs = std::experimental::filesystem; 13 | using namespace std; 14 | using namespace Gtk; 15 | using namespace Glib; 16 | 17 | #endif 18 | -------------------------------------------------------------------------------- /library.h: -------------------------------------------------------------------------------- 1 | // trim function 2 | ustring trim(ustring& str) { 3 | size_t first = str.find_first_not_of(' '); 4 | size_t last = str.find_last_not_of(' '); 5 | 6 | if (first == std::string::npos || last == std::string::npos) // not found 7 | return str; 8 | 9 | return str.substr(first, (last-first+1)); 10 | } 11 | 12 | // limit length of string 13 | ustring limit(string str, int len) { 14 | 15 | if (str.size() < len) return str; 16 | 17 | int charsread = 0; 18 | string result; 19 | char c; 20 | while(charsread < len) { 21 | c = str.at(charsread); 22 | 23 | result += c; 24 | charsread++; 25 | } 26 | return result; 27 | } 28 | -------------------------------------------------------------------------------- /main.cpp: -------------------------------------------------------------------------------- 1 | #include "browser.h" 2 | #include 3 | #include 4 | #include 5 | 6 | int main( int argc, char **argv) { 7 | try { 8 | // get path contains exe file 9 | char result[PATH_MAX]; 10 | ssize_t count = readlink("/proc/self/exe", result, PATH_MAX); 11 | string exe_path = string(result, (count > 0) ? count : 0); 12 | exe_path = fs::path(exe_path).parent_path().string(); 13 | //~ cout << "exe_path: " << exe_path << endl; 14 | 15 | Glib::RefPtr app = Gtk::Application::create(argc, argv, "dbt.tbrowser"); 16 | Browser browser(exe_path); 17 | 18 | app->run(browser); 19 | } 20 | catch(exception const& e) { 21 | //~ cerr << e.what() << endl; 22 | 23 | std::ofstream log("error.txt", std::ios_base::out | std::ios_base::app); 24 | log << e.what() << std::endl; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /makefile: -------------------------------------------------------------------------------- 1 | CC=g++ -Wall 2 | CLANG = clang++ -std=c++14 -O3 3 | CCACHE=ccache 4 | GTK=`pkg-config gtk+-3.0 --cflags` 5 | GTKMM=`pkg-config gtkmm-3.0 --cflags --libs` 6 | WEBKITGTK=`pkg-config webkit2gtk-4.0 --cflags --libs` 7 | #~ SQLITE=`pkg-config sqlite3 --cflags --libs` 8 | SQLITE=-lsqlite3 9 | FILESYS=-lstdc++fs 10 | BOOST=-lboost_filesystem -lboost_system 11 | 12 | SRC=main.cpp browser.cpp model.cpp blacklist.cpp 13 | OBJ=$(SRC:.cpp=.o) 14 | 15 | EXE=main 16 | 17 | # 'game' executable 18 | all: $(EXE) 19 | 20 | $(EXE) : $(OBJ) 21 | $(CCACHE) $(CLANG) $(OBJ) -o $@ $(WEBKITGTK) $(GTKMM) $(GTK) $(SQLITE) $(FILESYS) 22 | 23 | .cpp.o: 24 | $(CCACHE) $(CLANG) -c $< -o $@ $(WEBKITGTK) $(GTKMM) $(GTK) $(SQLITE) $(FILESYS) 25 | 26 | clean: 27 | rm *.o $(EXE) 28 | 29 | -------------------------------------------------------------------------------- /model.cpp: -------------------------------------------------------------------------------- 1 | #include "model.h" 2 | 3 | ModelColumns::ModelColumns() { 4 | add(column_title); 5 | add(column_address); 6 | } 7 | 8 | AddressModelColumn::AddressModelColumn() { 9 | add(column_name); 10 | add(column_address); 11 | } 12 | -------------------------------------------------------------------------------- /model.h: -------------------------------------------------------------------------------- 1 | #ifndef MODEL_H 2 | #define MODEL_H 3 | #include "header.h" 4 | 5 | class ModelColumns : public TreeModelColumnRecord { 6 | public: 7 | ModelColumns(); 8 | 9 | TreeModelColumn column_title; 10 | TreeModelColumn column_address; 11 | }; 12 | 13 | class AddressModelColumn : public TreeModelColumnRecord { 14 | public: 15 | AddressModelColumn(); 16 | 17 | TreeModelColumn column_name; 18 | TreeModelColumn column_address; 19 | }; 20 | 21 | #endif 22 | -------------------------------------------------------------------------------- /screenshot/browser.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bthachdev/web_browser/a3a08d9f6ba517e25e1075aa9e87ad7d5c6b1b96/screenshot/browser.png -------------------------------------------------------------------------------- /screenshot/browser2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bthachdev/web_browser/a3a08d9f6ba517e25e1075aa9e87ad7d5c6b1b96/screenshot/browser2.png -------------------------------------------------------------------------------- /tab.cpp: -------------------------------------------------------------------------------- 1 | #include "tab.h" 2 | 3 | void Tab::set_label(string name) { 4 | label.set_label(name); 5 | } 6 | 7 | Tab::~Tab() { 8 | 9 | } 10 | 11 | Tab::Tab() { 12 | set_border_width(2); 13 | 14 | label.set_text("New Tab"); 15 | x.set_label("x"); 16 | //~ x.set_text("x"); 17 | 18 | pack_start(label, PACK_SHRINK, 4); 19 | pack_start(x, PACK_SHRINK, 4); 20 | } 21 | -------------------------------------------------------------------------------- /tab.h: -------------------------------------------------------------------------------- 1 | #ifndef TAB_H 2 | #define TAB_H 3 | 4 | #include "header.h" 5 | 6 | class Tab : public HBox { 7 | public: 8 | Tab(); 9 | ~Tab(); 10 | 11 | void set_label(string); 12 | void set_id(int _id) { id = _id; } 13 | int get_id() { return id; } 14 | 15 | protected: 16 | Label label; 17 | Button x; 18 | //~ Label x; 19 | int id; 20 | }; 21 | 22 | #endif 23 | -------------------------------------------------------------------------------- /tproject.config: -------------------------------------------------------------------------------- 1 | make 2 | ./main 3 | -------------------------------------------------------------------------------- /webview.cpp: -------------------------------------------------------------------------------- 1 | #include "webview.h" 2 | 3 | WebView::~WebView() { 4 | //~ delete view; 5 | } 6 | 7 | void WebView::hide() { 8 | cout << "hide"; 9 | VBox::hide(); 10 | } 11 | 12 | void WebView::load_uri(string uri) { 13 | string final_uri; 14 | if (uri.find("http") > 0) 15 | final_uri = "http://"; 16 | final_uri.append(uri); 17 | 18 | webkit_web_view_load_uri(view, final_uri.c_str()); 19 | } 20 | 21 | WebView::WebView() { 22 | view = WEBKIT_WEB_VIEW(webkit_web_view_new()); 23 | Widget* widget = manage(Glib::wrap(GTK_WIDGET(view))); 24 | pack_start(*widget, PACK_EXPAND_WIDGET); 25 | } 26 | 27 | 28 | -------------------------------------------------------------------------------- /webview.h: -------------------------------------------------------------------------------- 1 | #ifndef WEBVIEW_H 2 | #define WEBVIEW_H 3 | 4 | #include "header.h" 5 | 6 | class WebView : public VBox { 7 | public: 8 | WebView(); 9 | ~WebView(); 10 | 11 | void load_uri(string uri); 12 | void hide(); 13 | 14 | WebKitWebView* get_webview() { return view; } 15 | void set_id(int _id) { id = _id; } 16 | int get_id() { return id; } 17 | 18 | protected: 19 | WebKitWebView* view; 20 | int id; 21 | }; 22 | 23 | #endif 24 | --------------------------------------------------------------------------------