Merge pull request #3045 from lightpanda-io/notificaiton-reregister-safe

cdp: ignore duplicate enable calls
This commit is contained in:
Karl Seguin
2026-07-24 19:24:32 +08:00
committed by GitHub
3 changed files with 14 additions and 21 deletions

View File

@@ -392,8 +392,20 @@ pub fn deinit(self: *Notification) void {
}
pub fn register(self: *Notification, comptime event: EventType, receiver: anytype, func: EventFunc(event)) !void {
var list = &@field(self.event_listeners, @tagName(event));
const allocator = self.allocator;
const gop = try self.listeners.getOrPut(allocator, @intFromPtr(receiver));
if (gop.found_existing) {
for (gop.value_ptr.items) |existing| {
if (existing.event == event) {
lp.assert(@as(*const anyopaque, @ptrCast(func)) == existing.func, "different notification callbacks per receiver", .{ .event = event });
return;
}
}
} else {
gop.value_ptr.* = .empty;
}
var list = &@field(self.event_listeners, @tagName(event));
var listener = try self.mem_pool.create();
errdefer self.mem_pool.destroy(listener);
@@ -405,12 +417,6 @@ pub fn register(self: *Notification, comptime event: EventType, receiver: anytyp
.func = @ptrCast(func),
.struct_name = @typeName(@typeInfo(@TypeOf(receiver)).pointer.child),
};
const allocator = self.allocator;
const gop = try self.listeners.getOrPut(allocator, @intFromPtr(receiver));
if (gop.found_existing == false) {
gop.value_ptr.* = .empty;
}
try gop.value_ptr.append(allocator, listener);
// we don't add this until we've successfully added the entry to

View File

@@ -569,10 +569,6 @@ pub const BrowserContext = struct {
http_proxy_changed: bool = false,
user_agent_changed: bool = false,
// True once we've registered for the download notifications, so repeated
// Browser.setDownloadBehavior calls don't add duplicate listeners.
download_events_registered: bool = false,
// Extra headers to add to all requests.
extra_headers: std.ArrayList([*c]const u8) = .empty,
@@ -826,6 +822,7 @@ pub const BrowserContext = struct {
}
pub fn fetchEnable(self: *BrowserContext, authRequests: bool) !void {
self.fetchDisable(); //in case of multiple calls
try self.notification.register(.http_request_intercept, self, onHttpRequestIntercept);
if (authRequests) {
try self.notification.register(.http_request_auth_required, self, onHttpRequestAuthRequired);
@@ -868,21 +865,13 @@ pub const BrowserContext = struct {
// Registers for the download notifications dispatched by Frame when a
// navigation is treated as a file download. Idempotent. See issue #2701.
pub fn downloadEventsEnable(self: *BrowserContext) !void {
if (self.download_events_registered) {
return;
}
try self.notification.register(.download_will_begin, self, onDownloadWillBegin);
try self.notification.register(.download_progress, self, onDownloadProgress);
self.download_events_registered = true;
}
pub fn downloadEventsDisable(self: *BrowserContext) void {
if (self.download_events_registered == false) {
return;
}
self.notification.unregister(.download_will_begin, self);
self.notification.unregister(.download_progress, self);
self.download_events_registered = false;
}
pub fn onDownloadWillBegin(ctx: *anyopaque, msg: *const Notification.DownloadWillBegin) !void {

View File

@@ -320,7 +320,6 @@ test "cdp.browser: setDownloadBehavior stores config on the session" {
try testing.expectEqual(.allow_and_name, bc.session.download_behavior);
try testing.expectEqualSlices(u8, "/tmp/lp-downloads", bc.session.download_path.?);
try testing.expect(bc.session.download_events_enabled);
try testing.expect(bc.download_events_registered);
// `default` maps to `deny` and tears the registration down again.
try ctx.processMessage(.{
@@ -331,7 +330,6 @@ test "cdp.browser: setDownloadBehavior stores config on the session" {
try testing.expectEqual(.deny, bc.session.download_behavior);
try testing.expect(bc.session.download_path == null);
try testing.expect(bc.session.download_events_enabled == false);
try testing.expect(bc.download_events_registered == false);
}
test "cdp.browser: setDownloadBehavior is a no-op when no context is loaded" {