bunite-core 0.11.0 → 0.11.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,210 @@
1
+ #pragma once
2
+
3
+ #include "../shared/ffi_exports.h"
4
+ #include "../shared/log.h"
5
+ #include "../shared/permissions.h"
6
+
7
+ #include <windows.h>
8
+ #include <wrl.h>
9
+
10
+ #include <atomic>
11
+ #include <chrono>
12
+ #include <cstdint>
13
+ #include <cstdio>
14
+ #include <cstring>
15
+ #include <deque>
16
+ #include <filesystem>
17
+ #include <fstream>
18
+ #include <functional>
19
+ #include <map>
20
+ #include <memory>
21
+ #include <mutex>
22
+ #include <optional>
23
+ #include <string>
24
+ #include <vector>
25
+
26
+ #include "WebView2.h"
27
+ #include "WebView2EnvironmentOptions.h"
28
+
29
+ namespace bunite_webview2 {
30
+
31
+ constexpr wchar_t kWindowClass[] = L"BuniteWebView2WindowClass";
32
+ constexpr wchar_t kViewContainerClass[] = L"BuniteWebView2ViewContainer";
33
+ constexpr UINT kRunQueuedTaskMessage = WM_APP + 1;
34
+
35
+ using Microsoft::WRL::ComPtr;
36
+
37
+ struct WindowHost;
38
+ struct ViewHost;
39
+
40
+ // Resolved synchronously by user-facing API; the COM completion handlers
41
+ // receive a weak_ptr<HostLifetime> guarding `state` so they can be torn down
42
+ // before WebView2 fires their last callback.
43
+ struct HostLifetime {
44
+ std::atomic<bool> alive{true};
45
+ };
46
+
47
+ struct PendingRouteRequest {
48
+ uint32_t view_id = 0;
49
+ std::wstring uri;
50
+ std::string path; // normalized path component
51
+ ComPtr<ICoreWebView2WebResourceRequestedEventArgs> args;
52
+ ComPtr<ICoreWebView2Deferral> deferral;
53
+ };
54
+
55
+ struct PendingPermissionRequest {
56
+ uint32_t view_id = 0;
57
+ uint32_t bunite_kind = 0; // BUNITE_PERMISSION_*
58
+ ComPtr<ICoreWebView2PermissionRequestedEventArgs> args;
59
+ ComPtr<ICoreWebView2Deferral> deferral;
60
+ };
61
+
62
+ struct ViewHost {
63
+ uint32_t id = 0;
64
+ WindowHost* window = nullptr;
65
+
66
+ // Pending state — applied either on bootstrap or via setters before the
67
+ // controller is ready.
68
+ std::string url;
69
+ std::string html;
70
+ std::string preload_script;
71
+ std::string appres_root;
72
+ std::vector<std::string> navigation_rules;
73
+ std::vector<std::string> preload_origins;
74
+ bool sandbox = false;
75
+ bool auto_resize = true;
76
+ RECT bounds{0, 0, 0, 0};
77
+ bool pending_visible = true;
78
+ bool pending_passthrough = false;
79
+
80
+ HWND container_hwnd = nullptr; // our own child HWND that hosts the controller
81
+ ComPtr<ICoreWebView2Controller> controller;
82
+ ComPtr<ICoreWebView2> webview;
83
+ ComPtr<ICoreWebView2Controller2> controller2;
84
+ ComPtr<ICoreWebView2_2> webview2;
85
+ std::wstring add_script_id; // returned by AddScriptToExecuteOnDocumentCreated
86
+
87
+ std::atomic<bool> ready{false};
88
+ std::atomic<bool> closing{false};
89
+ };
90
+
91
+ struct WindowHost {
92
+ uint32_t id = 0;
93
+ HWND hwnd = nullptr;
94
+ std::wstring title;
95
+ std::wstring title_bar_style;
96
+ bool transparent = false;
97
+ bool hidden = false;
98
+ bool minimized = false;
99
+ bool maximized = false;
100
+ std::atomic<bool> close_pending{false};
101
+ std::atomic<bool> closing{false};
102
+ std::vector<ViewHost*> views;
103
+ };
104
+
105
+ struct RuntimeState {
106
+ std::atomic<bool> initialized{false};
107
+ std::atomic<bool> shutting_down{false};
108
+ HWND message_window = nullptr;
109
+
110
+ std::mutex task_mutex;
111
+ std::deque<std::function<void()>> queued_tasks;
112
+
113
+ std::mutex object_mutex;
114
+ std::map<uint32_t, WindowHost*> windows_by_id;
115
+ std::map<uint32_t, ViewHost*> views_by_id;
116
+
117
+ std::mutex route_mutex;
118
+ std::map<uint32_t, PendingRouteRequest> pending_routes;
119
+ uint32_t next_route_request_id = 1;
120
+ std::vector<std::string> registered_routes; // paths
121
+
122
+ std::mutex permission_mutex;
123
+ std::map<uint32_t, PendingPermissionRequest> pending_permissions;
124
+ uint32_t next_permission_request_id = 1;
125
+
126
+ BuniteWebviewEventHandler webview_event_handler = nullptr;
127
+ BuniteWindowEventHandler window_event_handler = nullptr;
128
+
129
+ std::shared_ptr<HostLifetime> lifetime;
130
+ ComPtr<ICoreWebView2Environment> env;
131
+ bool env_pending = false;
132
+ bool env_ready = false;
133
+ std::vector<std::function<void()>> env_waiters;
134
+
135
+ // engine_config_json values
136
+ std::wstring user_data_folder;
137
+ std::wstring additional_browser_arguments;
138
+ std::wstring language;
139
+ bool popup_blocking = false;
140
+ };
141
+
142
+ extern RuntimeState g_runtime;
143
+
144
+ // --- runtime.cpp -----------------------------------------------------------
145
+
146
+ bool initRuntime(const char* engine_dir, bool hide_console,
147
+ bool popup_blocking, const char* engine_config_json);
148
+ void shutdownRuntime();
149
+ void pumpOnce();
150
+ void postUiTask(std::function<void()> task);
151
+ void executeQueuedUiTasks();
152
+ HINSTANCE getCurrentModuleHandle();
153
+ bool registerWindowClasses();
154
+
155
+ bool createWindow(uint32_t window_id, double x, double y, double w, double h,
156
+ const char* title, const char* title_bar_style,
157
+ bool transparent, bool hidden, bool minimized, bool maximized);
158
+ void destroyWindow(uint32_t window_id);
159
+ WindowHost* getWindow(uint32_t id);
160
+
161
+ bool createView(uint32_t view_id, uint32_t window_id,
162
+ const char* url, const char* html,
163
+ const char* preload, const char* appres_root,
164
+ const char* navigation_rules_json,
165
+ double x, double y, double w, double h,
166
+ bool auto_resize, bool sandbox,
167
+ const char* preload_origins_json);
168
+ ViewHost* getView(uint32_t id);
169
+ void destroyView(uint32_t id);
170
+
171
+ void emitWindowEvent(uint32_t window_id, const char* name, const std::string& payload = {});
172
+ void emitWebviewEvent(uint32_t view_id, const char* name, const std::string& payload = {});
173
+
174
+ // --- appres.cpp ------------------------------------------------------------
175
+
176
+ // Configures the env (created in runtime.cpp) with appres:// scheme + global
177
+ // WebResourceRequested handler. Called once from `ensureEnvironment()`.
178
+ void configureSchemes(ICoreWebView2EnvironmentOptions* opts);
179
+ void attachAppResFilter(ViewHost* view);
180
+ void registerAppResRoute(const char* path);
181
+ void unregisterAppResRoute(const char* path);
182
+ void completeRouteRequest(uint32_t request_id, const char* html);
183
+ void cancelAllRouteRequests();
184
+
185
+ // --- utils.cpp -------------------------------------------------------------
186
+
187
+ std::wstring utf8ToWide(const std::string& s);
188
+ std::string wideToUtf8(const std::wstring& s);
189
+ std::string wideToUtf8(LPCWSTR s);
190
+ std::string escapeJsonString(const std::string& s);
191
+
192
+ bool globMatchCaseInsensitive(const std::string& pattern, const std::string& value);
193
+ std::vector<std::string> parseNavigationRulesJson(const std::string& json);
194
+ std::vector<std::string> parsePreloadOriginsJson(const std::string& json);
195
+
196
+ // engine_config_json shape: { "userDataFolder": "...", "additionalBrowserArguments": "...", "language": "..." }
197
+ void parseEngineConfig(const std::string& json, std::wstring& user_data,
198
+ std::wstring& browser_args, std::wstring& language);
199
+
200
+ std::string normalizeAppResPath(const std::string& url);
201
+ std::string getMimeType(const std::filesystem::path& p);
202
+ std::string defaultUserDataFolder(); // %LOCALAPPDATA%\Bunite\WebView2
203
+ std::wstring exeDir();
204
+
205
+ uint32_t permissionKindToBuniteBit(COREWEBVIEW2_PERMISSION_KIND kind);
206
+ COREWEBVIEW2_PERMISSION_STATE buniteStateToWebView2(uint32_t state);
207
+
208
+ bool shouldAllowNavigation(const ViewHost* view, const std::string& url);
209
+
210
+ } // namespace bunite_webview2