From 77bc7063534ab317a2ef96249a4f78198d01ef01 Mon Sep 17 00:00:00 2001
From: Szontágh Ferenc <szf@fsociety.hu>
Date: Wed, 12 Mar 2025 23:46:55 +0000
Subject: [PATCH] initial
---
.gitignore | 6
src/base/wxBrowserBase.cpp | 88 ++++
assets/gui.fbp | 646 +++++++++++++++++++++++++++++
src/base/wxBrowserBase.h | 73 +++
src/handlers/WebViewHandler.h | 107 ++++
src/BrowserApp.cpp | 7
CMakeLists.txt | 17
src/handlers/CurlHttpsHandler.h | 87 +++
src/BrowserFrame.cpp | 150 ++++++
src/BrowserFrame.h | 54 ++
src/main.cpp | 4
src/BrowserApp.h | 12
src/handlers/CurlHttpHandler.h | 67 +++
13 files changed, 1,318 insertions(+), 0 deletions(-)
diff --git a/.gitignore b/.gitignore
index 0def275..6b087c4 100644
--- a/.gitignore
+++ b/.gitignore
@@ -19,3 +19,9 @@
*.exe
*.out
*.app
+
+.cache
+.DS_Store
+.vscode
+.idea
+build
\ No newline at end of file
diff --git a/CMakeLists.txt b/CMakeLists.txt
new file mode 100644
index 0000000..8c00b58
--- /dev/null
+++ b/CMakeLists.txt
@@ -0,0 +1,17 @@
+cmake_minimum_required(VERSION 3.10)
+project(wxWidgetsBrowser)
+
+
+find_package(CURL REQUIRED)
+
+find_package(wxWidgets REQUIRED COMPONENTS core base webview aui)
+include(${wxWidgets_USE_FILE})
+
+add_executable(wxWidgetsBrowser
+ src/main.cpp
+ src/BrowserApp.cpp
+ src/BrowserFrame.cpp
+ src/base/wxBrowserBase.cpp
+)
+
+target_link_libraries(wxWidgetsBrowser ${wxWidgets_LIBRARIES} ${CURL_LIBRARIES})
diff --git a/assets/gui.fbp b/assets/gui.fbp
new file mode 100644
index 0000000..be8d5d2
--- /dev/null
+++ b/assets/gui.fbp
@@ -0,0 +1,646 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<wxFormBuilder_Project>
+ <FileVersion major="1" minor="18"/>
+ <object class="Project" expanded="true">
+ <property name="code_generation">C++</property>
+ <property name="cpp_class_decoration">; </property>
+ <property name="cpp_disconnect_events">0</property>
+ <property name="cpp_event_generation">connect</property>
+ <property name="cpp_help_provider">none</property>
+ <property name="cpp_namespace"></property>
+ <property name="cpp_precompiled_header"></property>
+ <property name="cpp_use_array_enum">0</property>
+ <property name="cpp_use_enum">1</property>
+ <property name="embedded_files_path">res</property>
+ <property name="encoding">UTF-8</property>
+ <property name="file">wxBrowserBase</property>
+ <property name="first_id">6000</property>
+ <property name="internationalize">1</property>
+ <property name="lua_skip_events">1</property>
+ <property name="lua_ui_table">UI</property>
+ <property name="name">wxBrowser</property>
+ <property name="path">../src/base</property>
+ <property name="php_disconnect_events">0</property>
+ <property name="php_disconnect_mode">source_name</property>
+ <property name="php_skip_events">1</property>
+ <property name="python_disconnect_events">0</property>
+ <property name="python_disconnect_mode">source_name</property>
+ <property name="python_image_path_wrapper_function_name"></property>
+ <property name="python_indent_with_spaces">1</property>
+ <property name="python_skip_events">1</property>
+ <property name="relative_path">1</property>
+ <property name="use_microsoft_bom">0</property>
+ <property name="use_native_eol">0</property>
+ <object class="Frame" expanded="true">
+ <property name="aui_managed">0</property>
+ <property name="aui_manager_style">wxAUI_MGR_DEFAULT</property>
+ <property name="bg"></property>
+ <property name="center">wxBOTH</property>
+ <property name="context_help"></property>
+ <property name="context_menu">1</property>
+ <property name="drag_accept_files">0</property>
+ <property name="enabled">1</property>
+ <property name="event_handler">impl_virtual</property>
+ <property name="extra_style"></property>
+ <property name="fg"></property>
+ <property name="font"></property>
+ <property name="hidden">0</property>
+ <property name="id">wxID_ANY</property>
+ <property name="maximum_size"></property>
+ <property name="minimum_size">-1,-1</property>
+ <property name="name">wxBrowserBase</property>
+ <property name="pos"></property>
+ <property name="size">800,600</property>
+ <property name="style">wxDEFAULT_FRAME_STYLE</property>
+ <property name="subclass">; ; forward_declare</property>
+ <property name="title">wxBrowser</property>
+ <property name="tooltip"></property>
+ <property name="two_step_creation">0</property>
+ <property name="window_extra_style"></property>
+ <property name="window_name"></property>
+ <property name="window_style">wxTAB_TRAVERSAL</property>
+ <property name="xrc_skip_sizer">1</property>
+ <object class="wxBoxSizer" expanded="true">
+ <property name="minimum_size"></property>
+ <property name="name">bSizer1</property>
+ <property name="orient">wxVERTICAL</property>
+ <property name="permission">none</property>
+ <object class="sizeritem" expanded="true">
+ <property name="border">5</property>
+ <property name="flag">wxEXPAND</property>
+ <property name="proportion">0</property>
+ <object class="wxBoxSizer" expanded="false">
+ <property name="minimum_size"></property>
+ <property name="name">bSizer2</property>
+ <property name="orient">wxHORIZONTAL</property>
+ <property name="permission">none</property>
+ <object class="sizeritem" expanded="false">
+ <property name="border">5</property>
+ <property name="flag">wxALL</property>
+ <property name="proportion">0</property>
+ <object class="wxButton" expanded="false">
+ <property name="BottomDockable">1</property>
+ <property name="LeftDockable">1</property>
+ <property name="RightDockable">1</property>
+ <property name="TopDockable">1</property>
+ <property name="aui_layer">0</property>
+ <property name="aui_name"></property>
+ <property name="aui_position">0</property>
+ <property name="aui_row">0</property>
+ <property name="auth_needed">0</property>
+ <property name="best_size"></property>
+ <property name="bg"></property>
+ <property name="bitmap">Load From Art Provider; wxART_GO_BACK; wxART_MENU</property>
+ <property name="caption"></property>
+ <property name="caption_visible">1</property>
+ <property name="center_pane">0</property>
+ <property name="close_button">1</property>
+ <property name="context_help"></property>
+ <property name="context_menu">1</property>
+ <property name="current"></property>
+ <property name="default">0</property>
+ <property name="default_pane">0</property>
+ <property name="disabled"></property>
+ <property name="dock">Dock</property>
+ <property name="dock_fixed">0</property>
+ <property name="docking">Left</property>
+ <property name="drag_accept_files">0</property>
+ <property name="enabled">1</property>
+ <property name="fg"></property>
+ <property name="floatable">1</property>
+ <property name="focus"></property>
+ <property name="font"></property>
+ <property name="gripper">0</property>
+ <property name="hidden">0</property>
+ <property name="id">wxID_ANY</property>
+ <property name="label">Back</property>
+ <property name="margins"></property>
+ <property name="markup">0</property>
+ <property name="max_size"></property>
+ <property name="maximize_button">0</property>
+ <property name="maximum_size"></property>
+ <property name="min_size"></property>
+ <property name="minimize_button">0</property>
+ <property name="minimum_size"></property>
+ <property name="moveable">1</property>
+ <property name="name">m_back</property>
+ <property name="pane_border">1</property>
+ <property name="pane_position"></property>
+ <property name="pane_size"></property>
+ <property name="permission">protected</property>
+ <property name="pin_button">1</property>
+ <property name="pos"></property>
+ <property name="position"></property>
+ <property name="pressed"></property>
+ <property name="resize">Resizable</property>
+ <property name="show">1</property>
+ <property name="size"></property>
+ <property name="style"></property>
+ <property name="subclass">; ; forward_declare</property>
+ <property name="toolbar_pane">0</property>
+ <property name="tooltip"></property>
+ <property name="validator_data_type"></property>
+ <property name="validator_style">wxFILTER_NONE</property>
+ <property name="validator_type">wxDefaultValidator</property>
+ <property name="validator_variable"></property>
+ <property name="window_extra_style"></property>
+ <property name="window_name"></property>
+ <property name="window_style"></property>
+ <event name="OnButtonClick">OnBack</event>
+ </object>
+ </object>
+ <object class="sizeritem" expanded="false">
+ <property name="border">5</property>
+ <property name="flag">wxALL</property>
+ <property name="proportion">0</property>
+ <object class="wxButton" expanded="false">
+ <property name="BottomDockable">1</property>
+ <property name="LeftDockable">1</property>
+ <property name="RightDockable">1</property>
+ <property name="TopDockable">1</property>
+ <property name="aui_layer">0</property>
+ <property name="aui_name"></property>
+ <property name="aui_position">0</property>
+ <property name="aui_row">0</property>
+ <property name="auth_needed">0</property>
+ <property name="best_size"></property>
+ <property name="bg"></property>
+ <property name="bitmap">Load From Art Provider; wxART_GO_FORWARD; wxART_MENU</property>
+ <property name="caption"></property>
+ <property name="caption_visible">1</property>
+ <property name="center_pane">0</property>
+ <property name="close_button">1</property>
+ <property name="context_help"></property>
+ <property name="context_menu">1</property>
+ <property name="current"></property>
+ <property name="default">0</property>
+ <property name="default_pane">0</property>
+ <property name="disabled"></property>
+ <property name="dock">Dock</property>
+ <property name="dock_fixed">0</property>
+ <property name="docking">Left</property>
+ <property name="drag_accept_files">0</property>
+ <property name="enabled">1</property>
+ <property name="fg"></property>
+ <property name="floatable">1</property>
+ <property name="focus"></property>
+ <property name="font"></property>
+ <property name="gripper">0</property>
+ <property name="hidden">0</property>
+ <property name="id">wxID_ANY</property>
+ <property name="label">Forward</property>
+ <property name="margins"></property>
+ <property name="markup">0</property>
+ <property name="max_size"></property>
+ <property name="maximize_button">0</property>
+ <property name="maximum_size"></property>
+ <property name="min_size"></property>
+ <property name="minimize_button">0</property>
+ <property name="minimum_size"></property>
+ <property name="moveable">1</property>
+ <property name="name">m_forward</property>
+ <property name="pane_border">1</property>
+ <property name="pane_position"></property>
+ <property name="pane_size"></property>
+ <property name="permission">protected</property>
+ <property name="pin_button">1</property>
+ <property name="pos"></property>
+ <property name="position"></property>
+ <property name="pressed"></property>
+ <property name="resize">Resizable</property>
+ <property name="show">1</property>
+ <property name="size"></property>
+ <property name="style"></property>
+ <property name="subclass">; ; forward_declare</property>
+ <property name="toolbar_pane">0</property>
+ <property name="tooltip"></property>
+ <property name="validator_data_type"></property>
+ <property name="validator_style">wxFILTER_NONE</property>
+ <property name="validator_type">wxDefaultValidator</property>
+ <property name="validator_variable"></property>
+ <property name="window_extra_style"></property>
+ <property name="window_name"></property>
+ <property name="window_style"></property>
+ <event name="OnButtonClick">OnForward</event>
+ </object>
+ </object>
+ <object class="sizeritem" expanded="false">
+ <property name="border">5</property>
+ <property name="flag">wxALL</property>
+ <property name="proportion">0</property>
+ <object class="wxButton" expanded="false">
+ <property name="BottomDockable">1</property>
+ <property name="LeftDockable">1</property>
+ <property name="RightDockable">1</property>
+ <property name="TopDockable">1</property>
+ <property name="aui_layer">0</property>
+ <property name="aui_name"></property>
+ <property name="aui_position">0</property>
+ <property name="aui_row">0</property>
+ <property name="auth_needed">0</property>
+ <property name="best_size"></property>
+ <property name="bg"></property>
+ <property name="bitmap">Load From Art Provider; wxART_GO_HOME; wxART_MENU</property>
+ <property name="caption"></property>
+ <property name="caption_visible">1</property>
+ <property name="center_pane">0</property>
+ <property name="close_button">1</property>
+ <property name="context_help"></property>
+ <property name="context_menu">1</property>
+ <property name="current"></property>
+ <property name="default">0</property>
+ <property name="default_pane">0</property>
+ <property name="disabled"></property>
+ <property name="dock">Dock</property>
+ <property name="dock_fixed">0</property>
+ <property name="docking">Left</property>
+ <property name="drag_accept_files">0</property>
+ <property name="enabled">1</property>
+ <property name="fg"></property>
+ <property name="floatable">1</property>
+ <property name="focus"></property>
+ <property name="font"></property>
+ <property name="gripper">0</property>
+ <property name="hidden">0</property>
+ <property name="id">wxID_ANY</property>
+ <property name="label">Home</property>
+ <property name="margins"></property>
+ <property name="markup">0</property>
+ <property name="max_size"></property>
+ <property name="maximize_button">0</property>
+ <property name="maximum_size"></property>
+ <property name="min_size"></property>
+ <property name="minimize_button">0</property>
+ <property name="minimum_size"></property>
+ <property name="moveable">1</property>
+ <property name="name">m_home</property>
+ <property name="pane_border">1</property>
+ <property name="pane_position"></property>
+ <property name="pane_size"></property>
+ <property name="permission">protected</property>
+ <property name="pin_button">1</property>
+ <property name="pos"></property>
+ <property name="position"></property>
+ <property name="pressed"></property>
+ <property name="resize">Resizable</property>
+ <property name="show">1</property>
+ <property name="size"></property>
+ <property name="style"></property>
+ <property name="subclass">; ; forward_declare</property>
+ <property name="toolbar_pane">0</property>
+ <property name="tooltip"></property>
+ <property name="validator_data_type"></property>
+ <property name="validator_style">wxFILTER_NONE</property>
+ <property name="validator_type">wxDefaultValidator</property>
+ <property name="validator_variable"></property>
+ <property name="window_extra_style"></property>
+ <property name="window_name"></property>
+ <property name="window_style"></property>
+ <event name="OnButtonClick">OnHome</event>
+ </object>
+ </object>
+ <object class="sizeritem" expanded="false">
+ <property name="border">5</property>
+ <property name="flag">wxALL</property>
+ <property name="proportion">0</property>
+ <object class="wxButton" expanded="false">
+ <property name="BottomDockable">1</property>
+ <property name="LeftDockable">1</property>
+ <property name="RightDockable">1</property>
+ <property name="TopDockable">1</property>
+ <property name="aui_layer">0</property>
+ <property name="aui_name"></property>
+ <property name="aui_position">0</property>
+ <property name="aui_row">0</property>
+ <property name="auth_needed">0</property>
+ <property name="best_size"></property>
+ <property name="bg"></property>
+ <property name="bitmap"></property>
+ <property name="caption"></property>
+ <property name="caption_visible">1</property>
+ <property name="center_pane">0</property>
+ <property name="close_button">1</property>
+ <property name="context_help"></property>
+ <property name="context_menu">1</property>
+ <property name="current"></property>
+ <property name="default">0</property>
+ <property name="default_pane">0</property>
+ <property name="disabled"></property>
+ <property name="dock">Dock</property>
+ <property name="dock_fixed">0</property>
+ <property name="docking">Left</property>
+ <property name="drag_accept_files">0</property>
+ <property name="enabled">1</property>
+ <property name="fg"></property>
+ <property name="floatable">1</property>
+ <property name="focus"></property>
+ <property name="font"></property>
+ <property name="gripper">0</property>
+ <property name="hidden">0</property>
+ <property name="id">wxID_ANY</property>
+ <property name="label">Refresh</property>
+ <property name="margins"></property>
+ <property name="markup">0</property>
+ <property name="max_size"></property>
+ <property name="maximize_button">0</property>
+ <property name="maximum_size"></property>
+ <property name="min_size"></property>
+ <property name="minimize_button">0</property>
+ <property name="minimum_size"></property>
+ <property name="moveable">1</property>
+ <property name="name">m_refresh</property>
+ <property name="pane_border">1</property>
+ <property name="pane_position"></property>
+ <property name="pane_size"></property>
+ <property name="permission">protected</property>
+ <property name="pin_button">1</property>
+ <property name="pos"></property>
+ <property name="position"></property>
+ <property name="pressed"></property>
+ <property name="resize">Resizable</property>
+ <property name="show">1</property>
+ <property name="size"></property>
+ <property name="style"></property>
+ <property name="subclass">; ; forward_declare</property>
+ <property name="toolbar_pane">0</property>
+ <property name="tooltip"></property>
+ <property name="validator_data_type"></property>
+ <property name="validator_style">wxFILTER_NONE</property>
+ <property name="validator_type">wxDefaultValidator</property>
+ <property name="validator_variable"></property>
+ <property name="window_extra_style"></property>
+ <property name="window_name"></property>
+ <property name="window_style"></property>
+ <event name="OnButtonClick">OnReload</event>
+ </object>
+ </object>
+ <object class="sizeritem" expanded="false">
+ <property name="border">5</property>
+ <property name="flag">wxALL</property>
+ <property name="proportion">1</property>
+ <object class="wxTextCtrl" expanded="false">
+ <property name="BottomDockable">1</property>
+ <property name="LeftDockable">1</property>
+ <property name="RightDockable">1</property>
+ <property name="TopDockable">1</property>
+ <property name="aui_layer">0</property>
+ <property name="aui_name"></property>
+ <property name="aui_position">0</property>
+ <property name="aui_row">0</property>
+ <property name="best_size"></property>
+ <property name="bg"></property>
+ <property name="caption"></property>
+ <property name="caption_visible">1</property>
+ <property name="center_pane">0</property>
+ <property name="close_button">1</property>
+ <property name="context_help"></property>
+ <property name="context_menu">1</property>
+ <property name="default_pane">0</property>
+ <property name="dock">Dock</property>
+ <property name="dock_fixed">0</property>
+ <property name="docking">Left</property>
+ <property name="drag_accept_files">0</property>
+ <property name="enabled">1</property>
+ <property name="fg"></property>
+ <property name="floatable">1</property>
+ <property name="font"></property>
+ <property name="gripper">0</property>
+ <property name="hidden">0</property>
+ <property name="id">wxID_ANY</property>
+ <property name="max_size"></property>
+ <property name="maximize_button">0</property>
+ <property name="maximum_size"></property>
+ <property name="maxlength">0</property>
+ <property name="min_size"></property>
+ <property name="minimize_button">0</property>
+ <property name="minimum_size"></property>
+ <property name="moveable">1</property>
+ <property name="name">m_urlbar</property>
+ <property name="pane_border">1</property>
+ <property name="pane_position"></property>
+ <property name="pane_size"></property>
+ <property name="permission">protected</property>
+ <property name="pin_button">1</property>
+ <property name="pos"></property>
+ <property name="resize">Resizable</property>
+ <property name="show">1</property>
+ <property name="size"></property>
+ <property name="style">wxTE_PROCESS_ENTER</property>
+ <property name="subclass">; ; forward_declare</property>
+ <property name="toolbar_pane">0</property>
+ <property name="tooltip"></property>
+ <property name="validator_data_type"></property>
+ <property name="validator_style">wxFILTER_NONE</property>
+ <property name="validator_type">wxDefaultValidator</property>
+ <property name="validator_variable"></property>
+ <property name="value"></property>
+ <property name="window_extra_style"></property>
+ <property name="window_name"></property>
+ <property name="window_style"></property>
+ <event name="OnLeftUp">m_urlbarOnLeftUp</event>
+ <event name="OnSetFocus">m_urlbarOnSetFocus</event>
+ <event name="OnTextEnter">OnUrlEnter</event>
+ </object>
+ </object>
+ </object>
+ </object>
+ <object class="sizeritem" expanded="false">
+ <property name="border">5</property>
+ <property name="flag">wxALL|wxEXPAND</property>
+ <property name="proportion">0</property>
+ <object class="wxGauge" expanded="false">
+ <property name="BottomDockable">1</property>
+ <property name="LeftDockable">1</property>
+ <property name="RightDockable">1</property>
+ <property name="TopDockable">1</property>
+ <property name="aui_layer">0</property>
+ <property name="aui_name"></property>
+ <property name="aui_position">0</property>
+ <property name="aui_row">0</property>
+ <property name="best_size"></property>
+ <property name="bg"></property>
+ <property name="caption"></property>
+ <property name="caption_visible">1</property>
+ <property name="center_pane">0</property>
+ <property name="close_button">1</property>
+ <property name="context_help"></property>
+ <property name="context_menu">1</property>
+ <property name="default_pane">0</property>
+ <property name="dock">Dock</property>
+ <property name="dock_fixed">0</property>
+ <property name="docking">Left</property>
+ <property name="drag_accept_files">0</property>
+ <property name="enabled">1</property>
+ <property name="fg"></property>
+ <property name="floatable">1</property>
+ <property name="font"></property>
+ <property name="gripper">0</property>
+ <property name="hidden">0</property>
+ <property name="id">wxID_ANY</property>
+ <property name="max_size"></property>
+ <property name="maximize_button">0</property>
+ <property name="maximum_size"></property>
+ <property name="min_size"></property>
+ <property name="minimize_button">0</property>
+ <property name="minimum_size"></property>
+ <property name="moveable">1</property>
+ <property name="name">m_gauge1</property>
+ <property name="pane_border">1</property>
+ <property name="pane_position"></property>
+ <property name="pane_size"></property>
+ <property name="permission">protected</property>
+ <property name="pin_button">1</property>
+ <property name="pos"></property>
+ <property name="range">100</property>
+ <property name="resize">Resizable</property>
+ <property name="show">1</property>
+ <property name="size"></property>
+ <property name="style">wxGA_HORIZONTAL</property>
+ <property name="subclass">; ; forward_declare</property>
+ <property name="toolbar_pane">0</property>
+ <property name="tooltip"></property>
+ <property name="validator_data_type"></property>
+ <property name="validator_style">wxFILTER_NONE</property>
+ <property name="validator_type">wxDefaultValidator</property>
+ <property name="validator_variable"></property>
+ <property name="value">0</property>
+ <property name="window_extra_style"></property>
+ <property name="window_name"></property>
+ <property name="window_style"></property>
+ </object>
+ </object>
+ <object class="sizeritem" expanded="false">
+ <property name="border">5</property>
+ <property name="flag">wxEXPAND | wxALL</property>
+ <property name="proportion">1</property>
+ <object class="wxAuiNotebook" expanded="false">
+ <property name="BottomDockable">1</property>
+ <property name="LeftDockable">1</property>
+ <property name="RightDockable">1</property>
+ <property name="TopDockable">1</property>
+ <property name="aui_layer">0</property>
+ <property name="aui_name"></property>
+ <property name="aui_position">0</property>
+ <property name="aui_row">0</property>
+ <property name="best_size"></property>
+ <property name="bg"></property>
+ <property name="caption"></property>
+ <property name="caption_visible">1</property>
+ <property name="center_pane">0</property>
+ <property name="close_button">1</property>
+ <property name="context_help"></property>
+ <property name="context_menu">1</property>
+ <property name="default_pane">0</property>
+ <property name="dock">Dock</property>
+ <property name="dock_fixed">0</property>
+ <property name="docking">Left</property>
+ <property name="drag_accept_files">0</property>
+ <property name="enabled">1</property>
+ <property name="fg"></property>
+ <property name="floatable">1</property>
+ <property name="font"></property>
+ <property name="gripper">0</property>
+ <property name="hidden">0</property>
+ <property name="id">wxID_ANY</property>
+ <property name="max_size"></property>
+ <property name="maximize_button">0</property>
+ <property name="maximum_size"></property>
+ <property name="min_size"></property>
+ <property name="minimize_button">0</property>
+ <property name="minimum_size"></property>
+ <property name="moveable">1</property>
+ <property name="name">m_auinotebook1</property>
+ <property name="pane_border">1</property>
+ <property name="pane_position"></property>
+ <property name="pane_size"></property>
+ <property name="permission">protected</property>
+ <property name="pin_button">1</property>
+ <property name="pos"></property>
+ <property name="resize">Resizable</property>
+ <property name="show">1</property>
+ <property name="size"></property>
+ <property name="style">wxAUI_NB_DEFAULT_STYLE</property>
+ <property name="subclass">; ; forward_declare</property>
+ <property name="tab_ctrl_height">64</property>
+ <property name="toolbar_pane">0</property>
+ <property name="tooltip"></property>
+ <property name="uniform_bitmap_size"></property>
+ <property name="window_extra_style"></property>
+ <property name="window_name"></property>
+ <property name="window_style"></property>
+ <event name="OnAuiNotebookPageChanged">OnPageChanged</event>
+ <event name="OnAuiNotebookPageChanging">OnPageChanging</event>
+ <event name="OnAuiNotebookPageClose">OnPageClose</event>
+ <event name="OnAuiNotebookPageClosed">OnPageClosed</event>
+ </object>
+ </object>
+ </object>
+ <object class="wxStatusBar" expanded="true">
+ <property name="bg"></property>
+ <property name="context_help"></property>
+ <property name="context_menu">1</property>
+ <property name="drag_accept_files">0</property>
+ <property name="enabled">1</property>
+ <property name="fg"></property>
+ <property name="fields">1</property>
+ <property name="font"></property>
+ <property name="hidden">0</property>
+ <property name="id">wxID_ANY</property>
+ <property name="maximum_size"></property>
+ <property name="minimum_size"></property>
+ <property name="name">m_statusBar1</property>
+ <property name="permission">protected</property>
+ <property name="pos"></property>
+ <property name="size"></property>
+ <property name="style">wxSTB_SIZEGRIP</property>
+ <property name="subclass">; ; forward_declare</property>
+ <property name="tooltip"></property>
+ <property name="window_extra_style"></property>
+ <property name="window_name"></property>
+ <property name="window_style"></property>
+ </object>
+ <object class="wxMenuBar" expanded="true">
+ <property name="bg"></property>
+ <property name="context_help"></property>
+ <property name="context_menu">1</property>
+ <property name="drag_accept_files">0</property>
+ <property name="enabled">1</property>
+ <property name="fg"></property>
+ <property name="font"></property>
+ <property name="hidden">0</property>
+ <property name="id">wxID_ANY</property>
+ <property name="maximum_size"></property>
+ <property name="minimum_size"></property>
+ <property name="name">m_menubar1</property>
+ <property name="permission">protected</property>
+ <property name="pos"></property>
+ <property name="size"></property>
+ <property name="style"></property>
+ <property name="subclass">; ; forward_declare</property>
+ <property name="tooltip"></property>
+ <property name="window_extra_style"></property>
+ <property name="window_name"></property>
+ <property name="window_style"></property>
+ <object class="wxMenu" expanded="true">
+ <property name="label">&File</property>
+ <property name="name">m_menu_file</property>
+ <property name="permission">protected</property>
+ <object class="wxMenuItem" expanded="true">
+ <property name="bitmap"></property>
+ <property name="checked">0</property>
+ <property name="enabled">1</property>
+ <property name="help">Open a new tab</property>
+ <property name="id">wxID_ANY</property>
+ <property name="kind">wxITEM_NORMAL</property>
+ <property name="label">New &tab</property>
+ <property name="name">m_menuItem1</property>
+ <property name="permission">none</property>
+ <property name="shortcut">CTRL+T</property>
+ <property name="unchecked_bitmap"></property>
+ <event name="OnMenuSelection">OnNewTab</event>
+ </object>
+ </object>
+ </object>
+ </object>
+ </object>
+</wxFormBuilder_Project>
diff --git a/src/BrowserApp.cpp b/src/BrowserApp.cpp
new file mode 100644
index 0000000..47738f5
--- /dev/null
+++ b/src/BrowserApp.cpp
@@ -0,0 +1,7 @@
+#include "BrowserApp.h"
+
+bool BrowserApp::OnInit() {
+ BrowserFrame *frame = new BrowserFrame(NULL);
+ frame->Show(true);
+ return true;
+}
diff --git a/src/BrowserApp.h b/src/BrowserApp.h
new file mode 100644
index 0000000..f177487
--- /dev/null
+++ b/src/BrowserApp.h
@@ -0,0 +1,12 @@
+#ifndef BROWSERAPP_H
+#define BROWSERAPP_H
+
+#include "BrowserFrame.h"
+#include <wx/wx.h>
+
+class BrowserApp : public wxApp {
+public:
+ virtual bool OnInit();
+};
+
+#endif // BROWSERAPP_H
diff --git a/src/BrowserFrame.cpp b/src/BrowserFrame.cpp
new file mode 100644
index 0000000..4e3bc6a
--- /dev/null
+++ b/src/BrowserFrame.cpp
@@ -0,0 +1,150 @@
+#include "BrowserFrame.h"
+#include "handlers/CurlHttpHandler.h"
+#include "handlers/CurlHttpsHandler.h"
+
+BrowserFrame::BrowserFrame(wxWindow *parent) : wxBrowserBase(parent) {
+ wxCommandEvent event;
+ event.SetString("https://www.google.com");
+ this->OnNewTab(event);
+}
+
+BrowserFrame::~BrowserFrame() { webViews.clear(); }
+
+void BrowserFrame::OnPageClose(wxAuiNotebookEvent &event) { event.Skip(); }
+void BrowserFrame::OnPageClosed(wxAuiNotebookEvent &event) {
+
+ // get the closed tab index
+ int closed = event.GetSelection();
+ // remove the tab from the map
+ this->webViewtabMap.erase(closed);
+ // remove the webview from the map
+ this->webViews.erase(this->webViewtabMap[closed]);
+ if (this->currentWebView == this->webViewtabMap[closed]) {
+ this->currentWebView = nullptr;
+ }
+ if (this->webViewtabMap.size() == 0) {
+ wxCommandEvent event = wxCommandEvent();
+ event.SetString("https://www.google.com");
+ this->OnNewTab(event);
+ }
+ event.Skip();
+}
+void BrowserFrame::OnPageChanging(wxAuiNotebookEvent &event) { event.Skip(); }
+void BrowserFrame::OnPageChanged(wxAuiNotebookEvent &event) { event.Skip(); }
+
+void BrowserFrame::OnUrlEnter(wxCommandEvent &event) {
+ wxString url = m_urlbar->GetValue();
+ if (!url.StartsWith("http://") && !url.StartsWith("https://")) {
+ wxRegEx domainRegex("^([a-zA-Z0-9-]+\\.)+[a-zA-Z]{2,}$");
+ url = domainRegex.Matches(url) ? "https://" + url
+ : "https://www.google.com/search?q=" + url;
+ this->m_urlbar->SetValue(url);
+ }
+
+ if (this->currentWebView) {
+ url.Prepend("p");
+ this->currentWebView->LoadURL(url);
+ }
+}
+void BrowserFrame::OnNewTab(wxCommandEvent &event) {
+ wxPanel *panel = new wxPanel(m_auinotebook1);
+ wxBoxSizer *sizer = new wxBoxSizer(wxVERTICAL);
+
+ wxString url = "https://www.google.com";
+ if (!event.GetString().IsEmpty()) {
+ url = event.GetString();
+ }
+
+ wxWebView *webView = wxWebView::New(panel, wxID_ANY, url);
+ webView->RegisterHandler(
+ wxSharedPtr<wxWebViewHandler>(new CurlHttpHandler()));
+ webView->RegisterHandler(
+ wxSharedPtr<wxWebViewHandler>(new CurlHttpsHandler()));
+ sizer->Add(webView, 1, wxEXPAND);
+ panel->SetSizer(sizer);
+ m_auinotebook1->AddPage(panel, "New Tab", true);
+ m_auinotebook1->SetSelection(m_auinotebook1->GetPageCount() - 1);
+ this->m_urlbar->SetValue(url);
+ this->currentWebView = webView;
+ this->webViews[webView] = std::make_shared<WebViewHandler>(
+ webView, std::bind(&BrowserFrame::WebViewHandlerCallback, this,
+ std::placeholders::_1, std::placeholders::_2,
+ std::placeholders::_3));
+ this->webViewtabMap[m_auinotebook1->GetPageCount() - 1] = webView;
+}
+void BrowserFrame::OnReload(wxCommandEvent &event) {
+ if (this->currentWebView) {
+ this->currentWebView->Reload();
+ }
+}
+
+void BrowserFrame::OnBack(wxCommandEvent &event) {
+ if (this->currentWebView) {
+ this->currentWebView->GoBack();
+ }
+}
+
+void BrowserFrame::OnForward(wxCommandEvent &event) {
+ if (this->currentWebView) {
+ this->currentWebView->GoForward();
+ }
+}
+void BrowserFrame::OnHome(wxCommandEvent &event) {
+ if (this->currentWebView) {
+ this->currentWebView->LoadURL("https://www.google.com");
+ }
+}
+void BrowserFrame::m_urlbarOnSetFocus(wxFocusEvent &event) {
+ this->m_urlbar->SetSelection(0, this->m_urlbar->GetValue().size());
+}
+
+void BrowserFrame::m_urlbarOnLeftUp(wxMouseEvent &event) {
+ this->m_urlbar->SetSelection(0, this->m_urlbar->GetValue().size());
+}
+
+size_t BrowserFrame::GetTabIndex(wxWebView *webView) {
+ for (auto &pair : this->webViewtabMap) {
+ if (pair.second == webView) {
+ return pair.first;
+ }
+ }
+ return wxNOT_FOUND;
+}
+
+void BrowserFrame::ChangeTabIndex(wxWebView *webView, int index) {
+ auto it = this->webViewtabMap.find(index);
+ if (it != this->webViewtabMap.end()) {
+ this->webViewtabMap[index] = webView;
+ this->webViewtabMap.erase(it);
+ }
+}
+
+void BrowserFrame::WebViewHandlerCallback(WebViewHandler::CallbackType type,
+ const wxString data,
+ WebViewHandler *handler) {
+ switch (type) {
+ case WebViewHandler::CallbackType::OnTitleChanged: {
+ const auto index = this->GetTabIndex(handler->GetwebView());
+ if (index == wxNOT_FOUND) {
+ return;
+ }
+ wxString title = data;
+ if (data.size() > 50) {
+ title = data.substr(0, 50) + "...";
+ this->m_auinotebook1->SetPageToolTip(index, data);
+ }
+ this->m_auinotebook1->SetPageText(index, data);
+
+ } break;
+ case WebViewHandler::CallbackType::OnNavigated:
+ this->m_urlbar->SetValue(data);
+ break;
+ case WebViewHandler::CallbackType::OnNewWindow: {
+ wxCommandEvent event = wxCommandEvent();
+ event.SetString(data);
+ this->OnNewTab(event);
+ } break;
+ default:
+ break;
+ }
+}
\ No newline at end of file
diff --git a/src/BrowserFrame.h b/src/BrowserFrame.h
new file mode 100644
index 0000000..6e6b8fc
--- /dev/null
+++ b/src/BrowserFrame.h
@@ -0,0 +1,54 @@
+#ifndef __BrowserFrame__
+#define __BrowserFrame__
+
+/**
+@file
+Subclass of BrowserFrame, which is generated by wxFormBuilder.
+*/
+#include <map>
+#include <memory>
+#include <wx/panel.h>
+#include <wx/regex.h>
+#include <wx/webview.h>
+
+#include "base/wxBrowserBase.h"
+#include "handlers/WebViewHandler.h"
+
+//// end generated include
+
+/** Implementing BrowserFrame */
+class BrowserFrame : public wxBrowserBase {
+protected:
+ // Handlers for BrowserFrame events.
+ void OnPageClose(wxAuiNotebookEvent &event) override;
+ void OnPageClosed(wxAuiNotebookEvent &event) override;
+ void OnPageChanging(wxAuiNotebookEvent &event) override;
+ void OnPageChanged(wxAuiNotebookEvent &event) override;
+ void OnUrlEnter(wxCommandEvent &event) override;
+ void OnNewTab(wxCommandEvent &event) override;
+ void OnReload(wxCommandEvent &event) override;
+ void OnBack(wxCommandEvent &event) override;
+ void OnForward(wxCommandEvent &event) override;
+ void OnHome(wxCommandEvent &event) override;
+ void m_urlbarOnSetFocus(wxFocusEvent &event) override;
+ void m_urlbarOnLeftUp(wxMouseEvent &event) override;
+
+public:
+ /** Constructor */
+ BrowserFrame(wxWindow *parent);
+ ~BrowserFrame();
+
+private:
+ // webview, tab position
+ std::map<wxWebView *, std::shared_ptr<WebViewHandler>> webViews;
+ std::map<int, wxWebView *> webViewtabMap;
+ int currentWebViewIndex = 0;
+ wxWebView *currentWebView = nullptr;
+
+ size_t GetTabIndex(wxWebView *webView);
+ void ChangeTabIndex(wxWebView *webView, int index);
+ void WebViewHandlerCallback(WebViewHandler::CallbackType type,
+ const wxString data, WebViewHandler *handler);
+};
+
+#endif // __BrowserFrame__
diff --git a/src/base/wxBrowserBase.cpp b/src/base/wxBrowserBase.cpp
new file mode 100644
index 0000000..918ea91
--- /dev/null
+++ b/src/base/wxBrowserBase.cpp
@@ -0,0 +1,88 @@
+///////////////////////////////////////////////////////////////////////////
+// C++ code generated with wxFormBuilder (version 4.2.1-0-g80c4cb6)
+// http://www.wxformbuilder.org/
+//
+// PLEASE DO *NOT* EDIT THIS FILE!
+///////////////////////////////////////////////////////////////////////////
+
+#include "wxBrowserBase.h"
+
+///////////////////////////////////////////////////////////////////////////
+
+wxBrowserBase::wxBrowserBase( wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style ) : wxFrame( parent, id, title, pos, size, style )
+{
+ this->SetSizeHints( wxSize( -1,-1 ), wxDefaultSize );
+
+ wxBoxSizer* bSizer1;
+ bSizer1 = new wxBoxSizer( wxVERTICAL );
+
+ wxBoxSizer* bSizer2;
+ bSizer2 = new wxBoxSizer( wxHORIZONTAL );
+
+ m_back = new wxButton( this, wxID_ANY, _("Back"), wxDefaultPosition, wxDefaultSize, 0 );
+
+ m_back->SetBitmap( wxArtProvider::GetBitmap( wxASCII_STR(wxART_GO_BACK), wxASCII_STR(wxART_MENU) ) );
+ bSizer2->Add( m_back, 0, wxALL, 5 );
+
+ m_forward = new wxButton( this, wxID_ANY, _("Forward"), wxDefaultPosition, wxDefaultSize, 0 );
+
+ m_forward->SetBitmap( wxArtProvider::GetBitmap( wxASCII_STR(wxART_GO_FORWARD), wxASCII_STR(wxART_MENU) ) );
+ bSizer2->Add( m_forward, 0, wxALL, 5 );
+
+ m_home = new wxButton( this, wxID_ANY, _("Home"), wxDefaultPosition, wxDefaultSize, 0 );
+
+ m_home->SetBitmap( wxArtProvider::GetBitmap( wxASCII_STR(wxART_GO_HOME), wxASCII_STR(wxART_MENU) ) );
+ bSizer2->Add( m_home, 0, wxALL, 5 );
+
+ m_refresh = new wxButton( this, wxID_ANY, _("Refresh"), wxDefaultPosition, wxDefaultSize, 0 );
+ bSizer2->Add( m_refresh, 0, wxALL, 5 );
+
+ m_urlbar = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxTE_PROCESS_ENTER );
+ bSizer2->Add( m_urlbar, 1, wxALL, 5 );
+
+
+ bSizer1->Add( bSizer2, 0, wxEXPAND, 5 );
+
+ m_gauge1 = new wxGauge( this, wxID_ANY, 100, wxDefaultPosition, wxDefaultSize, wxGA_HORIZONTAL );
+ m_gauge1->SetValue( 0 );
+ bSizer1->Add( m_gauge1, 0, wxALL|wxEXPAND, 5 );
+
+ m_auinotebook1 = new wxAuiNotebook( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxAUI_NB_DEFAULT_STYLE );
+
+ bSizer1->Add( m_auinotebook1, 1, wxEXPAND | wxALL, 5 );
+
+
+ this->SetSizer( bSizer1 );
+ this->Layout();
+ m_statusBar1 = this->CreateStatusBar( 1, wxSTB_SIZEGRIP, wxID_ANY );
+ m_menubar1 = new wxMenuBar( 0 );
+ m_menu_file = new wxMenu();
+ wxMenuItem* m_menuItem1;
+ m_menuItem1 = new wxMenuItem( m_menu_file, wxID_ANY, wxString( _("New &tab") ) + wxT('\t') + wxT("CTRL+T"), _("Open a new tab"), wxITEM_NORMAL );
+ m_menu_file->Append( m_menuItem1 );
+
+ m_menubar1->Append( m_menu_file, _("&File") );
+
+ this->SetMenuBar( m_menubar1 );
+
+
+ this->Centre( wxBOTH );
+
+ // Connect Events
+ m_back->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( wxBrowserBase::OnBack ), NULL, this );
+ m_forward->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( wxBrowserBase::OnForward ), NULL, this );
+ m_home->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( wxBrowserBase::OnHome ), NULL, this );
+ m_refresh->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( wxBrowserBase::OnReload ), NULL, this );
+ m_urlbar->Connect( wxEVT_LEFT_UP, wxMouseEventHandler( wxBrowserBase::m_urlbarOnLeftUp ), NULL, this );
+ m_urlbar->Connect( wxEVT_SET_FOCUS, wxFocusEventHandler( wxBrowserBase::m_urlbarOnSetFocus ), NULL, this );
+ m_urlbar->Connect( wxEVT_COMMAND_TEXT_ENTER, wxCommandEventHandler( wxBrowserBase::OnUrlEnter ), NULL, this );
+ m_auinotebook1->Connect( wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGED, wxAuiNotebookEventHandler( wxBrowserBase::OnPageChanged ), NULL, this );
+ m_auinotebook1->Connect( wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGING, wxAuiNotebookEventHandler( wxBrowserBase::OnPageChanging ), NULL, this );
+ m_auinotebook1->Connect( wxEVT_COMMAND_AUINOTEBOOK_PAGE_CLOSE, wxAuiNotebookEventHandler( wxBrowserBase::OnPageClose ), NULL, this );
+ m_auinotebook1->Connect( wxEVT_COMMAND_AUINOTEBOOK_PAGE_CLOSED, wxAuiNotebookEventHandler( wxBrowserBase::OnPageClosed ), NULL, this );
+ m_menu_file->Bind(wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( wxBrowserBase::OnNewTab ), this, m_menuItem1->GetId());
+}
+
+wxBrowserBase::~wxBrowserBase()
+{
+}
diff --git a/src/base/wxBrowserBase.h b/src/base/wxBrowserBase.h
new file mode 100644
index 0000000..0dc6a3f
--- /dev/null
+++ b/src/base/wxBrowserBase.h
@@ -0,0 +1,73 @@
+///////////////////////////////////////////////////////////////////////////
+// C++ code generated with wxFormBuilder (version 4.2.1-0-g80c4cb6)
+// http://www.wxformbuilder.org/
+//
+// PLEASE DO *NOT* EDIT THIS FILE!
+///////////////////////////////////////////////////////////////////////////
+
+#pragma once
+
+#include <wx/artprov.h>
+#include <wx/xrc/xmlres.h>
+#include <wx/intl.h>
+#include <wx/button.h>
+#include <wx/string.h>
+#include <wx/bitmap.h>
+#include <wx/image.h>
+#include <wx/icon.h>
+#include <wx/gdicmn.h>
+#include <wx/font.h>
+#include <wx/colour.h>
+#include <wx/settings.h>
+#include <wx/textctrl.h>
+#include <wx/sizer.h>
+#include <wx/gauge.h>
+#include <wx/aui/auibook.h>
+#include <wx/statusbr.h>
+#include <wx/menu.h>
+#include <wx/frame.h>
+
+///////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////
+/// Class wxBrowserBase
+///////////////////////////////////////////////////////////////////////////////
+class wxBrowserBase : public wxFrame
+{
+ private:
+
+ protected:
+ wxButton* m_back;
+ wxButton* m_forward;
+ wxButton* m_home;
+ wxButton* m_refresh;
+ wxTextCtrl* m_urlbar;
+ wxGauge* m_gauge1;
+ wxAuiNotebook* m_auinotebook1;
+ wxStatusBar* m_statusBar1;
+ wxMenuBar* m_menubar1;
+ wxMenu* m_menu_file;
+
+ // Virtual event handlers, override them in your derived class
+ virtual void OnBack( wxCommandEvent& event ) { event.Skip(); }
+ virtual void OnForward( wxCommandEvent& event ) { event.Skip(); }
+ virtual void OnHome( wxCommandEvent& event ) { event.Skip(); }
+ virtual void OnReload( wxCommandEvent& event ) { event.Skip(); }
+ virtual void m_urlbarOnLeftUp( wxMouseEvent& event ) { event.Skip(); }
+ virtual void m_urlbarOnSetFocus( wxFocusEvent& event ) { event.Skip(); }
+ virtual void OnUrlEnter( wxCommandEvent& event ) { event.Skip(); }
+ virtual void OnPageChanged( wxAuiNotebookEvent& event ) { event.Skip(); }
+ virtual void OnPageChanging( wxAuiNotebookEvent& event ) { event.Skip(); }
+ virtual void OnPageClose( wxAuiNotebookEvent& event ) { event.Skip(); }
+ virtual void OnPageClosed( wxAuiNotebookEvent& event ) { event.Skip(); }
+ virtual void OnNewTab( wxCommandEvent& event ) { event.Skip(); }
+
+
+ public:
+
+ wxBrowserBase( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("wxBrowser"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( 800,600 ), long style = wxDEFAULT_FRAME_STYLE|wxTAB_TRAVERSAL );
+
+ ~wxBrowserBase();
+
+};
+
diff --git a/src/handlers/CurlHttpHandler.h b/src/handlers/CurlHttpHandler.h
new file mode 100644
index 0000000..0b37b98
--- /dev/null
+++ b/src/handlers/CurlHttpHandler.h
@@ -0,0 +1,67 @@
+#ifndef CURL_HTTP_HANDLER_H
+#define CURL_HTTP_HANDLER_H
+
+#include <curl/curl.h>
+#include <map>
+#include <wx/filesys.h>
+#include <wx/log.h>
+#include <wx/mstream.h>
+#include <wx/webview.h>
+
+class CurlHttpHandler : public wxWebViewHandler {
+public:
+ CurlHttpHandler() : wxWebViewHandler("phttp") {}
+
+ wxFSFile *GetFile(const wxString &uri) override {
+ wxLogMessage("Curl HTTP Handler: Loading %s", uri);
+
+ // Check cache first
+ if (cache.find(uri) != cache.end()) {
+ return new wxFSFile(
+ new wxMemoryInputStream(cache[uri].data(), cache[uri].size()), uri,
+ "text/html", wxEmptyString, wxDateTime::Now());
+ new wxMemoryInputStream(cache[uri].data(), cache[uri].size()), uri,
+ "text/html";
+ }
+
+ // Fetch content using curl
+ std::string content = FetchURL(uri.ToStdString());
+ if (content.empty()) {
+ wxLogError("Failed to load %s", uri);
+ return nullptr;
+ }
+
+ // Cache the response
+ std::vector<char> buffer(content.begin(), content.end());
+ cache[uri] = buffer;
+
+ return new wxFSFile(
+ new wxMemoryInputStream(cache[uri].data(), cache[uri].size()), uri,
+ "text/html", wxEmptyString, wxDateTime::Now());
+ }
+
+private:
+ static size_t WriteCallback(void *contents, size_t size, size_t nmemb,
+ std::string *output) {
+ size_t totalSize = size * nmemb;
+ output->append((char *)contents, totalSize);
+ return totalSize;
+ }
+
+ std::string FetchURL(const std::string &url) {
+ CURL *curl = curl_easy_init();
+ std::string response;
+ if (curl) {
+ curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
+ curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteCallback);
+ curl_easy_setopt(curl, CURLOPT_WRITEDATA, &response);
+ curl_easy_perform(curl);
+ curl_easy_cleanup(curl);
+ }
+ return response;
+ }
+
+ std::map<wxString, std::vector<char>> cache;
+};
+
+#endif // CURL_HTTP_HANDLER_H
\ No newline at end of file
diff --git a/src/handlers/CurlHttpsHandler.h b/src/handlers/CurlHttpsHandler.h
new file mode 100644
index 0000000..9834a06
--- /dev/null
+++ b/src/handlers/CurlHttpsHandler.h
@@ -0,0 +1,87 @@
+#ifndef CURL_HTTPS_HANDLER_H
+#define CURL_HTTPS_HANDLER_H
+
+#include <curl/curl.h>
+#include <iostream>
+#include <map>
+#include <wx/filesys.h>
+#include <wx/log.h>
+#include <wx/mstream.h>
+#include <wx/webview.h>
+
+class CurlHttpsHandler : public wxWebViewHandler {
+public:
+ CurlHttpsHandler() : wxWebViewHandler("phttps") {}
+
+ wxFSFile *GetFile(const wxString &url) override {
+ wxString uri = url.SubString(1, url.length() - 1);
+
+ std::cout << "CurlHttpsHandler::GetFile called with uri: " << uri
+ << std::endl;
+
+ // Check cache first
+ if (cache.find(uri) != cache.end()) {
+ return new wxFSFile(
+ new wxMemoryInputStream(cache[uri].data(), cache[uri].size()), uri,
+ "text/html", wxEmptyString, wxDateTime::Now());
+ new wxMemoryInputStream(cache[uri].data(), cache[uri].size()), uri,
+ "text/html";
+ }
+
+ // Fetch content using curl
+ std::pair<std::string, std::string> response = FetchURL(uri.ToStdString());
+ if (response.second.empty()) {
+ wxLogError("Failed to load %s", response.first);
+ return nullptr;
+ }
+ auto content = response.second;
+ std::string finalUrl = response.first;
+ uri = wxString::FromUTF8(finalUrl.c_str());
+
+ // Cache the response
+ std::vector<char> buffer(content.begin(), content.end());
+ cache[uri] = buffer;
+
+ return new wxFSFile(
+ new wxMemoryInputStream(cache[uri].data(), cache[uri].size()), uri,
+ "text/html", wxEmptyString, wxDateTime::Now());
+ }
+
+private:
+ static size_t WriteCallback(void *contents, size_t size, size_t nmemb,
+ std::string *output) {
+ size_t totalSize = size * nmemb;
+ output->append((char *)contents, totalSize);
+ return totalSize;
+ }
+
+ std::pair<std::string, std::string> FetchURL(const std::string &url) {
+ CURL *curl = curl_easy_init();
+ std::string response;
+ std::string finalUrl;
+
+ if (curl) {
+ curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
+ curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteCallback);
+ curl_easy_setopt(curl, CURLOPT_WRITEDATA, &response);
+ curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION,
+ 1L);
+
+ if (curl_easy_perform(curl) == CURLE_OK) {
+ char *effectiveUrl = nullptr;
+ curl_easy_getinfo(curl, CURLINFO_EFFECTIVE_URL, &effectiveUrl);
+ if (effectiveUrl) {
+ finalUrl = effectiveUrl;
+ }
+ }
+
+ curl_easy_cleanup(curl);
+ }
+
+ return {finalUrl, response};
+ }
+
+ std::map<wxString, std::vector<char>> cache;
+};
+
+#endif // CURL_HTTPS_HANDLER_H
\ No newline at end of file
diff --git a/src/handlers/WebViewHandler.h b/src/handlers/WebViewHandler.h
new file mode 100644
index 0000000..5f5e8d6
--- /dev/null
+++ b/src/handlers/WebViewHandler.h
@@ -0,0 +1,107 @@
+#ifndef WEBVIEWHANDLER_H
+#define WEBVIEWHANDLER_H
+#include <iostream>
+#include <wx/log.h>
+#include <wx/webview.h>
+
+class WebViewHandler {
+
+public:
+ enum class CallbackType {
+ OnNavigating,
+ OnNavigated,
+ OnLoaded,
+ OnError,
+ OnNewWindow,
+ OnTitleChanged,
+ };
+
+ typedef std::function<void(CallbackType, const wxString, WebViewHandler *)>
+ callback_t;
+
+ WebViewHandler(wxWebView *webView, callback_t clb = nullptr)
+ : m_webView(webView), callback(clb) {
+ if (m_webView) {
+ m_webView->Bind(wxEVT_WEBVIEW_NAVIGATING, &WebViewHandler::OnNavigating,
+ this);
+ m_webView->Bind(wxEVT_WEBVIEW_NAVIGATED, &WebViewHandler::OnNavigated,
+ this);
+ m_webView->Bind(wxEVT_WEBVIEW_LOADED, &WebViewHandler::OnLoaded, this);
+ m_webView->Bind(wxEVT_WEBVIEW_ERROR, &WebViewHandler::OnError, this);
+ m_webView->Bind(wxEVT_WEBVIEW_NEWWINDOW, &WebViewHandler::OnNewWindow,
+ this);
+ m_webView->Bind(wxEVT_WEBVIEW_TITLE_CHANGED,
+ &WebViewHandler::OnTitleChanged, this);
+ }
+ }
+
+ virtual ~WebViewHandler() {
+ if (m_webView) {
+ m_webView->Unbind(wxEVT_WEBVIEW_NAVIGATING, &WebViewHandler::OnNavigating,
+ this);
+ m_webView->Unbind(wxEVT_WEBVIEW_NAVIGATED, &WebViewHandler::OnNavigated,
+ this);
+ m_webView->Unbind(wxEVT_WEBVIEW_LOADED, &WebViewHandler::OnLoaded, this);
+ m_webView->Unbind(wxEVT_WEBVIEW_ERROR, &WebViewHandler::OnError, this);
+ m_webView->Unbind(wxEVT_WEBVIEW_NEWWINDOW, &WebViewHandler::OnNewWindow,
+ this);
+ }
+ }
+
+ wxWebView *GetwebView() { return m_webView; }
+
+protected:
+ virtual void OnNavigating(wxWebViewEvent &event) {
+ if (this->callback) {
+ this->callback(CallbackType::OnNavigating, event.GetURL(), this);
+ }
+ std::cout << "Navigating to: " << event.GetURL() << std::endl;
+ }
+ virtual void OnTitleChanged(wxWebViewEvent &event) {
+ wxString title = event.GetString();
+ if (title.IsEmpty()) {
+ title = m_webView->GetCurrentTitle();
+ }
+ if (title.IsEmpty()) {
+ return;
+ }
+ if (this->callback) {
+ this->callback(CallbackType::OnTitleChanged, title, this);
+ }
+ std::cout << "Title changed: " << title << std::endl;
+ }
+
+ virtual void OnNavigated(wxWebViewEvent &event) {
+ if (this->callback) {
+ this->callback(CallbackType::OnNavigated, event.GetURL(), this);
+ }
+ std::cout << "Navigating to: " << event.GetURL() << std::endl;
+ }
+
+ virtual void OnLoaded(wxWebViewEvent &event) {
+ if (this->callback) {
+ this->callback(CallbackType::OnLoaded, event.GetURL(), this);
+ }
+ std::cout << "Page loaded: " << event.GetURL() << std::endl;
+ }
+
+ virtual void OnError(wxWebViewEvent &event) {
+ if (this->callback) {
+ this->callback(CallbackType::OnError, event.GetString(), this);
+ }
+ std::cout << "Error loading page: " << event.GetString() << std::endl;
+ }
+
+ virtual void OnNewWindow(wxWebViewEvent &event) {
+ if (this->callback) {
+ this->callback(CallbackType::OnNewWindow, event.GetURL(), this);
+ }
+ std::cout << "New window requested: " << event.GetURL() << std::endl;
+ }
+
+private:
+ wxWebView *m_webView;
+ callback_t callback = nullptr;
+};
+
+#endif // WEBVIEWHANDLER_H
\ No newline at end of file
diff --git a/src/main.cpp b/src/main.cpp
new file mode 100644
index 0000000..9ddce02
--- /dev/null
+++ b/src/main.cpp
@@ -0,0 +1,4 @@
+#include "BrowserApp.h"
+#include <wx/wx.h>
+
+wxIMPLEMENT_APP(BrowserApp);
--
Gitblit v1.9.3