Skip to content

Commit 3f51961

Browse files
committed
Install GTK and WebKit libs
1 parent 0ee025c commit 3f51961

6 files changed

Lines changed: 50 additions & 130 deletions

File tree

build.zig

Lines changed: 2 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -296,27 +296,15 @@ pub fn build(b: *Build) void {
296296
vfs_step.dependOn(&run_vfs_gen.step);
297297

298298
const examples_step = b.step("examples", "Build all Zig ported examples");
299-
if (linux_webview_host_install_step) |host_install| {
300-
examples_step.dependOn(host_install);
301-
}
302-
if (linux_browser_host_install_step) |host_install| {
303-
examples_step.dependOn(host_install);
304-
}
305299
var selected_example_found = selected_example == .all;
306300
if (example_shared_mod) |shared_mod| {
307301
for (examples) |example| {
308302
if (!pathExists(example.source_path)) continue;
309303

310304
const built = addExample(b, example, webui_mod, shared_mod, webui_lib, target, optimize, runtime_helpers_assets.prepare_step);
311305
examples_step.dependOn(built.install_step);
312-
if (linux_webview_host_install_step) |host_install| {
313-
built.install_step.dependOn(host_install);
314-
built.run_step.dependOn(host_install);
315-
}
316-
if (linux_browser_host_install_step) |host_install| {
317-
built.install_step.dependOn(host_install);
318-
built.run_step.dependOn(host_install);
319-
}
306+
if (linux_webview_host_install_step) |host_install| built.run_step.dependOn(host_install);
307+
if (linux_browser_host_install_step) |host_install| built.run_step.dependOn(host_install);
320308

321309
if (selected_example == .all or selected_example == example.selector) {
322310
selected_example_found = true;

parity/status.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313

1414
{ "id": "browser.discovery.catalog", "status": "implemented", "tests": ["browser_discovery.test.catalog includes browser_driver and webui browser families"] },
1515
{ "id": "browser.discovery.env_precedence", "status": "implemented", "tests": ["browser_discovery.test.required browser matrix coverage is present across all os specs"] },
16-
{ "id": "browser.launch.fallback", "status": "implemented", "tests": ["root.test.lifecycle config enables heartbeat without tracked child browser"] },
16+
{ "id": "browser.launch.fallback", "status": "implemented", "tests": ["root.test.non-linked tracked browser pid death requests close"] },
1717
{ "id": "browser.launch.prompt_quiet_defaults", "status": "implemented", "tests": ["ported.webui.test.quiet prompt policy injects suppression flags for chromium family"] },
1818
{ "id": "browser.launch.prompt_opt_in", "status": "implemented", "tests": ["ported.webui.test.browser default preset disables quiet flags unless explicitly re-enabled"] },
1919
{ "id": "browser.launch.browser_specific_flags", "status": "implemented", "tests": ["ported.webui.test.edge and brave receive browser-specific quiet flags"] },

src/bridge/generated/runtime_helpers.embed.js

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -215,6 +215,9 @@ let __webuiSocketOpen = false;
215215
let __webuiSocketStopped = false;
216216
let __webuiSocketReconnectDelayMs = 120;
217217
let __webuiSocketQueue = [];
218+
let __webuiSocketEverOpened = false;
219+
let __webuiSocketFailedAttempts = 0;
220+
const __webuiSocketMaxFailedAttemptsBeforeStop = 8;
218221

219222
function __webuiSocketUrl() {
220223
try {
@@ -319,6 +322,10 @@ function __webuiConnectPushSocket() {
319322
if (typeof globalThis === "undefined") return;
320323
if (__webuiSocketStopped) return;
321324
if (typeof globalThis.WebSocket !== "function") return;
325+
if (!__webuiSocketEverOpened && __webuiSocketFailedAttempts >= __webuiSocketMaxFailedAttemptsBeforeStop) {
326+
__webuiSocketStopped = true;
327+
return;
328+
}
322329
if (__webuiSocket && (__webuiSocket.readyState === globalThis.WebSocket.CONNECTING || __webuiSocket.readyState === globalThis.WebSocket.OPEN)) return;
323330

324331
const url = __webuiSocketUrl();
@@ -335,6 +342,8 @@ function __webuiConnectPushSocket() {
335342
__webuiSocket = socket;
336343
socket.onopen = () => {
337344
__webuiSocketOpen = true;
345+
__webuiSocketEverOpened = true;
346+
__webuiSocketFailedAttempts = 0;
338347
__webuiSocketReconnectDelayMs = 120;
339348
__webuiSocketFlushQueue();
340349
};
@@ -346,6 +355,12 @@ function __webuiConnectPushSocket() {
346355
__webuiSocketOpen = false;
347356
__webuiSocket = null;
348357
if (__webuiSocketStopped) return;
358+
__webuiSocketFailedAttempts += 1;
359+
if (!__webuiSocketEverOpened && __webuiSocketFailedAttempts >= __webuiSocketMaxFailedAttemptsBeforeStop) {
360+
__webuiSocketStopped = true;
361+
__webuiSocketQueue = [];
362+
return;
363+
}
349364
const delay = Math.min(1500, __webuiSocketReconnectDelayMs);
350365
__webuiSocketReconnectDelayMs = Math.min(2500, __webuiSocketReconnectDelayMs * 2);
351366
setTimeout(__webuiConnectPushSocket, delay);
@@ -453,7 +468,6 @@ async function __webuiExecuteScriptTask(task) {
453468
globalThis.__webuiWindowStyle = __webuiWindowStyle;
454469
globalThis.__webuiGetWindowStyle = __webuiGetWindowStyle;
455470
globalThis.__webuiGetWindowCapabilities = __webuiGetWindowCapabilities;
456-
setTimeout(() => { __webuiGetWindowStyle().catch(() => {}); }, 0);
457471
}
458472
})();
459473

src/bridge/generated/runtime_helpers.written.js

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -215,6 +215,9 @@ let __webuiSocketOpen = false;
215215
let __webuiSocketStopped = false;
216216
let __webuiSocketReconnectDelayMs = 120;
217217
let __webuiSocketQueue = [];
218+
let __webuiSocketEverOpened = false;
219+
let __webuiSocketFailedAttempts = 0;
220+
const __webuiSocketMaxFailedAttemptsBeforeStop = 8;
218221

219222
function __webuiSocketUrl() {
220223
try {
@@ -319,6 +322,10 @@ function __webuiConnectPushSocket() {
319322
if (typeof globalThis === "undefined") return;
320323
if (__webuiSocketStopped) return;
321324
if (typeof globalThis.WebSocket !== "function") return;
325+
if (!__webuiSocketEverOpened && __webuiSocketFailedAttempts >= __webuiSocketMaxFailedAttemptsBeforeStop) {
326+
__webuiSocketStopped = true;
327+
return;
328+
}
322329
if (__webuiSocket && (__webuiSocket.readyState === globalThis.WebSocket.CONNECTING || __webuiSocket.readyState === globalThis.WebSocket.OPEN)) return;
323330

324331
const url = __webuiSocketUrl();
@@ -335,6 +342,8 @@ function __webuiConnectPushSocket() {
335342
__webuiSocket = socket;
336343
socket.onopen = () => {
337344
__webuiSocketOpen = true;
345+
__webuiSocketEverOpened = true;
346+
__webuiSocketFailedAttempts = 0;
338347
__webuiSocketReconnectDelayMs = 120;
339348
__webuiSocketFlushQueue();
340349
};
@@ -346,6 +355,12 @@ function __webuiConnectPushSocket() {
346355
__webuiSocketOpen = false;
347356
__webuiSocket = null;
348357
if (__webuiSocketStopped) return;
358+
__webuiSocketFailedAttempts += 1;
359+
if (!__webuiSocketEverOpened && __webuiSocketFailedAttempts >= __webuiSocketMaxFailedAttemptsBeforeStop) {
360+
__webuiSocketStopped = true;
361+
__webuiSocketQueue = [];
362+
return;
363+
}
349364
const delay = Math.min(1500, __webuiSocketReconnectDelayMs);
350365
__webuiSocketReconnectDelayMs = Math.min(2500, __webuiSocketReconnectDelayMs * 2);
351366
setTimeout(__webuiConnectPushSocket, delay);
@@ -453,6 +468,5 @@ async function __webuiExecuteScriptTask(task) {
453468
globalThis.__webuiWindowStyle = __webuiWindowStyle;
454469
globalThis.__webuiGetWindowStyle = __webuiGetWindowStyle;
455470
globalThis.__webuiGetWindowCapabilities = __webuiGetWindowCapabilities;
456-
setTimeout(() => { __webuiGetWindowStyle().catch(() => {}); }, 0);
457471
}
458472
})();

src/bridge/runtime_helpers.source.js

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -215,6 +215,9 @@ let __webuiSocketOpen = false;
215215
let __webuiSocketStopped = false;
216216
let __webuiSocketReconnectDelayMs = 120;
217217
let __webuiSocketQueue = [];
218+
let __webuiSocketEverOpened = false;
219+
let __webuiSocketFailedAttempts = 0;
220+
const __webuiSocketMaxFailedAttemptsBeforeStop = 8;
218221

219222
function __webuiSocketUrl() {
220223
try {
@@ -319,6 +322,10 @@ function __webuiConnectPushSocket() {
319322
if (typeof globalThis === "undefined") return;
320323
if (__webuiSocketStopped) return;
321324
if (typeof globalThis.WebSocket !== "function") return;
325+
if (!__webuiSocketEverOpened && __webuiSocketFailedAttempts >= __webuiSocketMaxFailedAttemptsBeforeStop) {
326+
__webuiSocketStopped = true;
327+
return;
328+
}
322329
if (__webuiSocket && (__webuiSocket.readyState === globalThis.WebSocket.CONNECTING || __webuiSocket.readyState === globalThis.WebSocket.OPEN)) return;
323330

324331
const url = __webuiSocketUrl();
@@ -335,6 +342,8 @@ function __webuiConnectPushSocket() {
335342
__webuiSocket = socket;
336343
socket.onopen = () => {
337344
__webuiSocketOpen = true;
345+
__webuiSocketEverOpened = true;
346+
__webuiSocketFailedAttempts = 0;
338347
__webuiSocketReconnectDelayMs = 120;
339348
__webuiSocketFlushQueue();
340349
};
@@ -346,6 +355,12 @@ function __webuiConnectPushSocket() {
346355
__webuiSocketOpen = false;
347356
__webuiSocket = null;
348357
if (__webuiSocketStopped) return;
358+
__webuiSocketFailedAttempts += 1;
359+
if (!__webuiSocketEverOpened && __webuiSocketFailedAttempts >= __webuiSocketMaxFailedAttemptsBeforeStop) {
360+
__webuiSocketStopped = true;
361+
__webuiSocketQueue = [];
362+
return;
363+
}
349364
const delay = Math.min(1500, __webuiSocketReconnectDelayMs);
350365
__webuiSocketReconnectDelayMs = Math.min(2500, __webuiSocketReconnectDelayMs * 2);
351366
setTimeout(__webuiConnectPushSocket, delay);
@@ -453,6 +468,5 @@ async function __webuiExecuteScriptTask(task) {
453468
globalThis.__webuiWindowStyle = __webuiWindowStyle;
454469
globalThis.__webuiGetWindowStyle = __webuiGetWindowStyle;
455470
globalThis.__webuiGetWindowCapabilities = __webuiGetWindowCapabilities;
456-
setTimeout(() => { __webuiGetWindowStyle().catch(() => {}); }, 0);
457471
}
458472
})();

src/root.zig

Lines changed: 2 additions & 112 deletions
Original file line numberDiff line numberDiff line change
@@ -167,33 +167,6 @@ const CloseCallbackState = struct {
167167
context: ?*anyopaque = null,
168168
};
169169

170-
const LifecycleConfig = struct {
171-
enable_heartbeat: bool,
172-
heartbeat_interval_ms: u32,
173-
heartbeat_hidden_interval_ms: u32,
174-
heartbeat_timeout_ms: u32,
175-
heartbeat_failures_before_close: u8,
176-
heartbeat_initial_delay_ms: u32,
177-
};
178-
179-
const lifecycle_child_process_config = LifecycleConfig{
180-
.enable_heartbeat = false,
181-
.heartbeat_interval_ms = 0,
182-
.heartbeat_hidden_interval_ms = 0,
183-
.heartbeat_timeout_ms = 0,
184-
.heartbeat_failures_before_close = 0,
185-
.heartbeat_initial_delay_ms = 0,
186-
};
187-
188-
const lifecycle_fallback_config = LifecycleConfig{
189-
.enable_heartbeat = true,
190-
.heartbeat_interval_ms = 1_200,
191-
.heartbeat_hidden_interval_ms = 3_000,
192-
.heartbeat_timeout_ms = 500,
193-
.heartbeat_failures_before_close = 2,
194-
.heartbeat_initial_delay_ms = 400,
195-
};
196-
197170
fn backendWarningForError(err: anyerror, will_fallback: bool) ?[]const u8 {
198171
return switch (err) {
199172
error.NativeBackendUnavailable => if (will_fallback)
@@ -1076,15 +1049,6 @@ const WindowState = struct {
10761049
_ = self.requestClose();
10771050
}
10781051

1079-
fn hasTrackedChildBrowser(self: *const WindowState) bool {
1080-
return self.launched_browser_lifecycle_linked;
1081-
}
1082-
1083-
fn lifecycleConfig(self: *const WindowState) LifecycleConfig {
1084-
if (self.hasTrackedChildBrowser()) return lifecycle_child_process_config;
1085-
return lifecycle_fallback_config;
1086-
}
1087-
10881052
fn terminateLaunchedBrowser(self: *WindowState, allocator: std.mem.Allocator) void {
10891053
if (self.launched_browser_pid) |pid| {
10901054
if (self.rpc_state.log_enabled) {
@@ -2585,7 +2549,6 @@ fn handleConnection(state: *WindowState, allocator: std.mem.Allocator, stream: s
25852549

25862550
if (try handleBridgeScriptRoute(state, allocator, stream, request.method, path_only)) return;
25872551
if (try handleRpcRoute(state, allocator, stream, request.method, path_only, request.headers, request.body)) return;
2588-
if (try handleLifecycleConfigRoute(state, allocator, stream, request.method, path_only)) return;
25892552
if (try handleLifecycleRoute(state, allocator, stream, request.method, path_only, request.headers, request.body)) return;
25902553
if (try handleScriptPullRoute(state, allocator, stream, request.method, path_only, request.headers)) return;
25912554
if (try handleScriptResponseRoute(state, allocator, stream, request.method, path_only, request.body)) return;
@@ -2596,27 +2559,6 @@ fn handleConnection(state: *WindowState, allocator: std.mem.Allocator, stream: s
25962559
try writeHttpResponse(stream, 404, "text/plain; charset=utf-8", "not found");
25972560
}
25982561

2599-
fn handleLifecycleConfigRoute(
2600-
state: *WindowState,
2601-
allocator: std.mem.Allocator,
2602-
stream: std.net.Stream,
2603-
method: []const u8,
2604-
path_only: []const u8,
2605-
) !bool {
2606-
if (!std.mem.eql(u8, method, "GET")) return false;
2607-
if (!std.mem.eql(u8, path_only, "/webui/lifecycle/config")) return false;
2608-
2609-
state.state_mutex.lock();
2610-
const config = state.lifecycleConfig();
2611-
state.state_mutex.unlock();
2612-
2613-
const payload = try std.json.Stringify.valueAlloc(allocator, config, .{});
2614-
defer allocator.free(payload);
2615-
2616-
try writeHttpResponse(stream, 200, "application/json; charset=utf-8", payload);
2617-
return true;
2618-
}
2619-
26202562
fn handleLifecycleRoute(
26212563
state: *WindowState,
26222564
allocator: std.mem.Allocator,
@@ -2631,7 +2573,6 @@ fn handleLifecycleRoute(
26312573

26322574
var parsed = std.json.parseFromSlice(std.json.Value, allocator, body, .{}) catch null;
26332575
var logged_event = false;
2634-
var heartbeat_event = false;
26352576
const client_token = httpHeaderValue(headers, "x-webui-client-id") orelse default_client_token;
26362577
state.state_mutex.lock();
26372578
_ = state.findOrCreateClientSessionLocked(client_token) catch null;
@@ -2646,10 +2587,7 @@ fn handleLifecycleRoute(
26462587
state.requestLifecycleCloseFromFrontend();
26472588
state.state_mutex.unlock();
26482589
}
2649-
if (std.mem.eql(u8, event_value.string, "heartbeat")) {
2650-
heartbeat_event = true;
2651-
}
2652-
if (state.rpc_state.log_enabled and !std.mem.eql(u8, event_value.string, "heartbeat")) {
2590+
if (state.rpc_state.log_enabled) {
26532591
std.debug.print("[webui.lifecycle] event={s}\n", .{event_value.string});
26542592
logged_event = true;
26552593
}
@@ -2658,7 +2596,7 @@ fn handleLifecycleRoute(
26582596
}
26592597
}
26602598

2661-
if (state.rpc_state.log_enabled and !logged_event and !heartbeat_event) {
2599+
if (state.rpc_state.log_enabled and !logged_event) {
26622600
std.debug.print("[webui.lifecycle] body={s}\n", .{body});
26632601
}
26642602

@@ -3416,54 +3354,6 @@ test "native_webview browser fallback can be disabled" {
34163354
try std.testing.expectError(error.TransportNotBrowserRenderable, win.browserUrl());
34173355
}
34183356

3419-
test "lifecycle config enables heartbeat without tracked child browser" {
3420-
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
3421-
defer _ = gpa.deinit();
3422-
3423-
var app = try App.init(gpa.allocator(), .{
3424-
.transport_mode = .browser_fallback,
3425-
.auto_open_browser = false,
3426-
});
3427-
defer app.deinit();
3428-
3429-
var win = try app.newWindow(.{ .title = "LifecycleConfigEnabled" });
3430-
try win.showHtml("<html><body>lifecycle-config</body></html>");
3431-
try app.run();
3432-
3433-
const response = try httpRoundTrip(gpa.allocator(), win.state().server_port, "GET", "/webui/lifecycle/config", null);
3434-
defer gpa.allocator().free(response);
3435-
3436-
try std.testing.expect(std.mem.indexOf(u8, response, "\"enable_heartbeat\":true") != null);
3437-
try std.testing.expect(std.mem.indexOf(u8, response, "\"heartbeat_interval_ms\":1200") != null);
3438-
try std.testing.expect(std.mem.indexOf(u8, response, "\"heartbeat_hidden_interval_ms\":3000") != null);
3439-
}
3440-
3441-
test "lifecycle config disables heartbeat for lifecycle-linked child launches" {
3442-
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
3443-
defer _ = gpa.deinit();
3444-
3445-
var app = try App.init(gpa.allocator(), .{
3446-
.transport_mode = .browser_fallback,
3447-
.auto_open_browser = false,
3448-
});
3449-
defer app.deinit();
3450-
3451-
var win = try app.newWindow(.{ .title = "LifecycleConfigDisabled" });
3452-
try win.showHtml("<html><body>lifecycle-config-child</body></html>");
3453-
try app.run();
3454-
3455-
win.state().state_mutex.lock();
3456-
win.state().launched_browser_is_child = true;
3457-
win.state().launched_browser_lifecycle_linked = true;
3458-
win.state().state_mutex.unlock();
3459-
3460-
const response = try httpRoundTrip(gpa.allocator(), win.state().server_port, "GET", "/webui/lifecycle/config", null);
3461-
defer gpa.allocator().free(response);
3462-
3463-
try std.testing.expect(std.mem.indexOf(u8, response, "\"enable_heartbeat\":false") != null);
3464-
try std.testing.expect(std.mem.indexOf(u8, response, "\"heartbeat_interval_ms\":0") != null);
3465-
}
3466-
34673357
test "linked child exit requests close immediately" {
34683358
if (builtin.os.tag == .windows or builtin.os.tag == .wasi) return error.SkipZigTest;
34693359

0 commit comments

Comments
 (0)