Skip to content

Commit 6c59266

Browse files
committed
Introduce more general notification capabilities
Replaces the existing, very specialized Notification with something more general. Currently, the existing page_navigate and page_navigated have been migrated. Telemetry's page navigation event now also hooks into these events to generate the telemetry record.
1 parent 2910f4f commit 6c59266

File tree

6 files changed

+310
-47
lines changed

6 files changed

+310
-47
lines changed

src/app.zig

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ const js = @import("runtime/js.zig");
55
const Loop = @import("runtime/loop.zig").Loop;
66
const HttpClient = @import("http/client.zig").Client;
77
const Telemetry = @import("telemetry/telemetry.zig").Telemetry;
8+
const Notification = @import("notification.zig").Notification;
89

910
const log = std.log.scoped(.app);
1011

@@ -17,6 +18,7 @@ pub const App = struct {
1718
telemetry: Telemetry,
1819
http_client: HttpClient,
1920
app_dir_path: ?[]const u8,
21+
notification: *Notification,
2022

2123
pub const RunMode = enum {
2224
help,
@@ -41,19 +43,24 @@ pub const App = struct {
4143
loop.* = try Loop.init(allocator);
4244
errdefer loop.deinit();
4345

46+
const notification = try Notification.init(allocator, null);
47+
errdefer notification.deinit();
48+
4449
const app_dir_path = getAndMakeAppDir(allocator);
4550

4651
app.* = .{
4752
.loop = loop,
4853
.allocator = allocator,
4954
.telemetry = undefined,
5055
.app_dir_path = app_dir_path,
56+
.notification = notification,
5157
.http_client = try HttpClient.init(allocator, 5, .{
5258
.tls_verify_host = config.tls_verify_host,
5359
}),
5460
.config = config,
5561
};
5662
app.telemetry = Telemetry.init(app, config.run_mode);
63+
try app.telemetry.register(app.notification);
5764

5865
return app;
5966
}
@@ -67,6 +74,7 @@ pub const App = struct {
6774
self.loop.deinit();
6875
allocator.destroy(self.loop);
6976
self.http_client.deinit();
77+
self.notification.deinit();
7078
allocator.destroy(self);
7179
}
7280
};

src/browser/browser.zig

Lines changed: 13 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ pub const Browser = struct {
5858
allocator: Allocator,
5959
http_client: *http.Client,
6060
page_arena: ArenaAllocator,
61+
notification: *Notification,
6162

6263
pub fn init(app: *App) !Browser {
6364
const allocator = app.allocator;
@@ -67,11 +68,15 @@ pub const Browser = struct {
6768
});
6869
errdefer env.deinit();
6970

71+
const notification = try Notification.init(allocator, app.notification);
72+
errdefer notification.deinit();
73+
7074
return .{
7175
.app = app,
7276
.env = env,
7377
.session = null,
7478
.allocator = allocator,
79+
.notification = notification,
7580
.http_client = &app.http_client,
7681
.page_arena = ArenaAllocator.init(allocator),
7782
};
@@ -81,13 +86,14 @@ pub const Browser = struct {
8186
self.closeSession();
8287
self.env.deinit();
8388
self.page_arena.deinit();
89+
self.notification.deinit();
8490
}
8591

86-
pub fn newSession(self: *Browser, ctx: anytype) !*Session {
92+
pub fn newSession(self: *Browser) !*Session {
8793
self.closeSession();
8894
self.session = @as(Session, undefined);
8995
const session = &self.session.?;
90-
try Session.init(session, self, ctx);
96+
try Session.init(session, self);
9197
return session;
9298
}
9399

@@ -119,32 +125,14 @@ pub const Session = struct {
119125

120126
page: ?Page = null,
121127

122-
// recipient of notification, passed as the first parameter to notify
123-
notify_ctx: *anyopaque,
124-
notify_func: *const fn (ctx: *anyopaque, notification: *const Notification) anyerror!void,
125-
126-
fn init(self: *Session, browser: *Browser, ctx: anytype) !void {
127-
const ContextT = @TypeOf(ctx);
128-
const ContextStruct = switch (@typeInfo(ContextT)) {
129-
.@"struct" => ContextT,
130-
.pointer => |ptr| ptr.child,
131-
.void => NoopContext,
132-
else => @compileError("invalid context type"),
133-
};
134-
135-
// ctx can be void, to be able to store it in our *anyopaque field, we
136-
// need to play a little game.
137-
const any_ctx: *anyopaque = if (@TypeOf(ctx) == void) @constCast(@ptrCast(&{})) else ctx;
138-
128+
fn init(self: *Session, browser: *Browser) !void {
139129
var executor = try browser.env.newExecutor();
140130
errdefer executor.deinit();
141131

142132
const allocator = browser.app.allocator;
143133
self.* = .{
144134
.browser = browser,
145135
.executor = executor,
146-
.notify_ctx = any_ctx,
147-
.notify_func = ContextStruct.notify,
148136
.arena = ArenaAllocator.init(allocator),
149137
.storage_shed = storage.Shed.init(allocator),
150138
.cookie_jar = storage.CookieJar.init(allocator),
@@ -213,12 +201,6 @@ pub const Session = struct {
213201
.reason = .anchor,
214202
});
215203
}
216-
217-
fn notify(self: *const Session, notification: *const Notification) void {
218-
self.notify_func(self.notify_ctx, notification) catch |err| {
219-
log.err("notify {}: {}", .{ std.meta.activeTag(notification.*), err });
220-
};
221-
}
222204
};
223205

224206
// Page navigates to an url.
@@ -350,20 +332,15 @@ pub const Page = struct {
350332
// redirect)
351333
self.url = request_url;
352334

353-
session.browser.app.telemetry.record(.{ .navigate = .{
354-
.proxy = false,
355-
.tls = std.ascii.eqlIgnoreCase(request_url.scheme(), "https"),
356-
} });
357-
358335
// load the data
359336
var request = try self.newHTTPRequest(.GET, &self.url, .{ .navigation = true });
360337
defer request.deinit();
361338

362-
session.notify(&.{ .page_navigate = .{
339+
session.browser.notification.dispatch(.page_navigate, &.{
363340
.url = &self.url,
364341
.reason = opts.reason,
365342
.timestamp = timestamp(),
366-
} });
343+
});
367344

368345
var response = try request.sendSync(.{});
369346

@@ -399,10 +376,10 @@ pub const Page = struct {
399376
self.raw_data = arr.items;
400377
}
401378

402-
session.notify(&.{ .page_navigated = .{
379+
session.browser.notification.dispatch(.page_navigated, &.{
403380
.url = &self.url,
404381
.timestamp = timestamp(),
405-
} });
382+
});
406383
}
407384

408385
// https://html.spec.whatwg.org/#read-html

src/cdp/cdp.zig

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -312,7 +312,7 @@ pub fn BrowserContext(comptime CDP_T: type) type {
312312
fn init(self: *Self, id: []const u8, cdp: *CDP_T) !void {
313313
const allocator = cdp.allocator;
314314

315-
const session = try cdp.browser.newSession(self);
315+
const session = try cdp.browser.newSession();
316316
const arena = session.arena.allocator();
317317

318318
const inspector = try cdp.browser.env.newInspector(arena, self);
@@ -337,6 +337,10 @@ pub fn BrowserContext(comptime CDP_T: type) type {
337337
.inspector = inspector,
338338
};
339339
self.node_search_list = Node.Search.List.init(allocator, &self.node_registry);
340+
errdefer self.deinit();
341+
342+
try cdp.browser.notification.register(.page_navigate, self, onPageNavigate);
343+
try cdp.browser.notification.register(.page_navigated, self, onPageNavigated);
340344
}
341345

342346
pub fn deinit(self: *Self) void {
@@ -352,6 +356,7 @@ pub fn BrowserContext(comptime CDP_T: type) type {
352356
}
353357
self.node_registry.deinit();
354358
self.node_search_list.deinit();
359+
self.cdp.browser.notification.unregisterAll(self);
355360
}
356361

357362
pub fn reset(self: *Self) void {
@@ -394,13 +399,14 @@ pub fn BrowserContext(comptime CDP_T: type) type {
394399
return if (raw_url.len == 0) null else raw_url;
395400
}
396401

397-
pub fn notify(ctx: *anyopaque, notification: *const Notification) !void {
402+
pub fn onPageNavigate(ctx: *anyopaque, data: *const Notification.PageNavigate) !void {
398403
const self: *Self = @alignCast(@ptrCast(ctx));
404+
return @import("domains/page.zig").pageNavigate(self, data);
405+
}
399406

400-
switch (notification.*) {
401-
.page_navigate => |*pn| return @import("domains/page.zig").pageNavigate(self, pn),
402-
.page_navigated => |*pn| return @import("domains/page.zig").pageNavigated(self, pn),
403-
}
407+
pub fn onPageNavigated(ctx: *anyopaque, data: *const Notification.PageNavigated) !void {
408+
const self: *Self = @alignCast(@ptrCast(ctx));
409+
return @import("domains/page.zig").pageNavigated(self, data);
404410
}
405411

406412
pub fn callInspector(self: *const Self, msg: []const u8) void {

src/main.zig

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ pub fn main() !void {
9797
var browser = try Browser.init(app);
9898
defer browser.deinit();
9999

100-
var session = try browser.newSession({});
100+
var session = try browser.newSession();
101101

102102
// page
103103
const page = try session.createPage();

0 commit comments

Comments
 (0)