mirror of
https://github.com/lightpanda-io/browser.git
synced 2026-03-30 17:18:57 +00:00
Removing remaining CDP generic
Follow up to https://github.com/lightpanda-io/browser/pull/1990 which makes both BrowserContext and Command non-generic.
This commit is contained in:
127
src/cdp/CDP.zig
127
src/cdp/CDP.zig
@@ -63,7 +63,7 @@ target_id_gen: TargetIdGen = .{},
|
|||||||
session_id_gen: SessionIdGen = .{},
|
session_id_gen: SessionIdGen = .{},
|
||||||
browser_context_id_gen: BrowserContextIdGen = .{},
|
browser_context_id_gen: BrowserContextIdGen = .{},
|
||||||
|
|
||||||
browser_context: ?BrowserContext(CDP),
|
browser_context: ?BrowserContext,
|
||||||
|
|
||||||
// Re-used arena for processing a message. We're assuming that we're getting
|
// Re-used arena for processing a message. We're assuming that we're getting
|
||||||
// 1 message at a time.
|
// 1 message at a time.
|
||||||
@@ -120,7 +120,7 @@ pub fn handleMessage(self: *CDP, msg: []const u8) bool {
|
|||||||
pub fn processMessage(self: *CDP, msg: []const u8) !void {
|
pub fn processMessage(self: *CDP, msg: []const u8) !void {
|
||||||
const arena = &self.message_arena;
|
const arena = &self.message_arena;
|
||||||
defer _ = arena.reset(.{ .retain_with_limit = 1024 * 16 });
|
defer _ = arena.reset(.{ .retain_with_limit = 1024 * 16 });
|
||||||
return self.dispatch(arena.allocator(), self, msg);
|
return self.dispatch(arena.allocator(), .{ .cdp = self }, msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
// @newhttp
|
// @newhttp
|
||||||
@@ -136,12 +136,12 @@ pub fn pageWait(self: *CDP, ms: u32) !Session.Runner.CDPWaitResult {
|
|||||||
// Called from above, in processMessage which handles client messages
|
// Called from above, in processMessage which handles client messages
|
||||||
// but can also be called internally. For example, Target.sendMessageToTarget
|
// but can also be called internally. For example, Target.sendMessageToTarget
|
||||||
// calls back into dispatch to capture the response.
|
// calls back into dispatch to capture the response.
|
||||||
pub fn dispatch(self: *CDP, arena: Allocator, sender: anytype, str: []const u8) !void {
|
pub fn dispatch(self: *CDP, arena: Allocator, sender: Command.Sender, str: []const u8) !void {
|
||||||
const input = json.parseFromSliceLeaky(InputMessage, arena, str, .{
|
const input = json.parseFromSliceLeaky(InputMessage, arena, str, .{
|
||||||
.ignore_unknown_fields = true,
|
.ignore_unknown_fields = true,
|
||||||
}) catch return error.InvalidJSON;
|
}) catch return error.InvalidJSON;
|
||||||
|
|
||||||
var command = Command(CDP, @TypeOf(sender)){
|
var command = Command{
|
||||||
.input = .{
|
.input = .{
|
||||||
.json = str,
|
.json = str,
|
||||||
.id = input.id,
|
.id = input.id,
|
||||||
@@ -186,7 +186,7 @@ pub fn dispatch(self: *CDP, arena: Allocator, sender: anytype, str: []const u8)
|
|||||||
// "special" handling - the bare minimum we need to do until the driver
|
// "special" handling - the bare minimum we need to do until the driver
|
||||||
// switches to a real BrowserContext.
|
// switches to a real BrowserContext.
|
||||||
// (I can imagine this logic will become driver-specific)
|
// (I can imagine this logic will become driver-specific)
|
||||||
fn dispatchStartupCommand(command: anytype, method: []const u8) !void {
|
fn dispatchStartupCommand(command: *Command, method: []const u8) !void {
|
||||||
// Stagehand parses the response and error if we don't return a
|
// Stagehand parses the response and error if we don't return a
|
||||||
// correct one for Page.getFrameTree on startup call.
|
// correct one for Page.getFrameTree on startup call.
|
||||||
if (std.mem.eql(u8, method, "Page.getFrameTree")) {
|
if (std.mem.eql(u8, method, "Page.getFrameTree")) {
|
||||||
@@ -197,7 +197,7 @@ fn dispatchStartupCommand(command: anytype, method: []const u8) !void {
|
|||||||
return command.sendResult(null, .{});
|
return command.sendResult(null, .{});
|
||||||
}
|
}
|
||||||
|
|
||||||
fn dispatchCommand(command: anytype, method: []const u8) !void {
|
fn dispatchCommand(command: *Command, method: []const u8) !void {
|
||||||
const domain = blk: {
|
const domain = blk: {
|
||||||
const i = std.mem.indexOfScalarPos(u8, method, 0, '.') orelse {
|
const i = std.mem.indexOfScalarPos(u8, method, 0, '.') orelse {
|
||||||
return error.InvalidMethod;
|
return error.InvalidMethod;
|
||||||
@@ -273,10 +273,10 @@ pub fn createBrowserContext(self: *CDP) ![]const u8 {
|
|||||||
}
|
}
|
||||||
const id = self.browser_context_id_gen.next();
|
const id = self.browser_context_id_gen.next();
|
||||||
|
|
||||||
self.browser_context = @as(BrowserContext(CDP), undefined);
|
self.browser_context = @as(BrowserContext, undefined);
|
||||||
const browser_context = &self.browser_context.?;
|
const browser_context = &self.browser_context.?;
|
||||||
|
|
||||||
try BrowserContext(CDP).init(browser_context, id, self);
|
try BrowserContext.init(browser_context, id, self);
|
||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -308,7 +308,7 @@ pub fn sendJSON(self: *CDP, message: anytype) !void {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn BrowserContext(comptime CDP_T: type) type {
|
pub const BrowserContext = struct {
|
||||||
const Node = @import("Node.zig");
|
const Node = @import("Node.zig");
|
||||||
const AXNode = @import("AXNode.zig");
|
const AXNode = @import("AXNode.zig");
|
||||||
|
|
||||||
@@ -317,9 +317,8 @@ pub fn BrowserContext(comptime CDP_T: type) type {
|
|||||||
data: std.ArrayList(u8),
|
data: std.ArrayList(u8),
|
||||||
};
|
};
|
||||||
|
|
||||||
return struct {
|
|
||||||
id: []const u8,
|
id: []const u8,
|
||||||
cdp: *CDP_T,
|
cdp: *CDP,
|
||||||
|
|
||||||
// Represents the browser session. There is no equivalent in CDP. For
|
// Represents the browser session. There is no equivalent in CDP. For
|
||||||
// all intents and purpose, from CDP's point of view our Browser and
|
// all intents and purpose, from CDP's point of view our Browser and
|
||||||
@@ -386,9 +385,7 @@ pub fn BrowserContext(comptime CDP_T: type) type {
|
|||||||
|
|
||||||
notification: *Notification,
|
notification: *Notification,
|
||||||
|
|
||||||
const Self = @This();
|
fn init(self: *BrowserContext, id: []const u8, cdp: *CDP) !void {
|
||||||
|
|
||||||
fn init(self: *Self, id: []const u8, cdp: *CDP_T) !void {
|
|
||||||
const allocator = cdp.allocator;
|
const allocator = cdp.allocator;
|
||||||
|
|
||||||
// Create notification for this BrowserContext
|
// Create notification for this BrowserContext
|
||||||
@@ -434,7 +431,7 @@ pub fn BrowserContext(comptime CDP_T: type) type {
|
|||||||
try notification.register(.page_frame_created, self, onPageFrameCreated);
|
try notification.register(.page_frame_created, self, onPageFrameCreated);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn deinit(self: *Self) void {
|
pub fn deinit(self: *BrowserContext) void {
|
||||||
const browser = &self.cdp.browser;
|
const browser = &self.cdp.browser;
|
||||||
const env = &browser.env;
|
const env = &browser.env;
|
||||||
|
|
||||||
@@ -480,12 +477,12 @@ pub fn BrowserContext(comptime CDP_T: type) type {
|
|||||||
self.intercept_state.deinit();
|
self.intercept_state.deinit();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn reset(self: *Self) void {
|
pub fn reset(self: *BrowserContext) void {
|
||||||
self.node_registry.reset();
|
self.node_registry.reset();
|
||||||
self.node_search_list.reset();
|
self.node_search_list.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn createIsolatedWorld(self: *Self, world_name: []const u8, grant_universal_access: bool) !*IsolatedWorld {
|
pub fn createIsolatedWorld(self: *BrowserContext, world_name: []const u8, grant_universal_access: bool) !*IsolatedWorld {
|
||||||
const browser = &self.cdp.browser;
|
const browser = &self.cdp.browser;
|
||||||
const arena = try browser.arena_pool.acquire(.{ .debug = "IsolatedWorld" });
|
const arena = try browser.arena_pool.acquire(.{ .debug = "IsolatedWorld" });
|
||||||
errdefer browser.arena_pool.release(arena);
|
errdefer browser.arena_pool.release(arena);
|
||||||
@@ -508,7 +505,7 @@ pub fn BrowserContext(comptime CDP_T: type) type {
|
|||||||
return world;
|
return world;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn nodeWriter(self: *Self, root: *const Node, opts: Node.Writer.Opts) Node.Writer {
|
pub fn nodeWriter(self: *BrowserContext, root: *const Node, opts: Node.Writer.Opts) Node.Writer {
|
||||||
return .{
|
return .{
|
||||||
.root = root,
|
.root = root,
|
||||||
.depth = opts.depth,
|
.depth = opts.depth,
|
||||||
@@ -517,7 +514,7 @@ pub fn BrowserContext(comptime CDP_T: type) type {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn axnodeWriter(self: *Self, root: *const Node, opts: AXNode.Writer.Opts) !AXNode.Writer {
|
pub fn axnodeWriter(self: *BrowserContext, root: *const Node, opts: AXNode.Writer.Opts) !AXNode.Writer {
|
||||||
const page = self.session.currentPage() orelse return error.PageNotLoaded;
|
const page = self.session.currentPage() orelse return error.PageNotLoaded;
|
||||||
_ = opts;
|
_ = opts;
|
||||||
return .{
|
return .{
|
||||||
@@ -527,13 +524,13 @@ pub fn BrowserContext(comptime CDP_T: type) type {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn getURL(self: *const Self) ?[:0]const u8 {
|
pub fn getURL(self: *const BrowserContext) ?[:0]const u8 {
|
||||||
const page = self.session.currentPage() orelse return null;
|
const page = self.session.currentPage() orelse return null;
|
||||||
const url = page.url;
|
const url = page.url;
|
||||||
return if (url.len == 0) null else url;
|
return if (url.len == 0) null else url;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn getTitle(self: *const Self) ?[]const u8 {
|
pub fn getTitle(self: *const BrowserContext) ?[]const u8 {
|
||||||
const page = self.session.currentPage() orelse return null;
|
const page = self.session.currentPage() orelse return null;
|
||||||
return page.getTitle() catch |err| {
|
return page.getTitle() catch |err| {
|
||||||
log.err(.cdp, "page title", .{ .err = err });
|
log.err(.cdp, "page title", .{ .err = err });
|
||||||
@@ -541,7 +538,7 @@ pub fn BrowserContext(comptime CDP_T: type) type {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn networkEnable(self: *Self) !void {
|
pub fn networkEnable(self: *BrowserContext) !void {
|
||||||
try self.notification.register(.http_request_fail, self, onHttpRequestFail);
|
try self.notification.register(.http_request_fail, self, onHttpRequestFail);
|
||||||
try self.notification.register(.http_request_start, self, onHttpRequestStart);
|
try self.notification.register(.http_request_start, self, onHttpRequestStart);
|
||||||
try self.notification.register(.http_request_done, self, onHttpRequestDone);
|
try self.notification.register(.http_request_done, self, onHttpRequestDone);
|
||||||
@@ -549,7 +546,7 @@ pub fn BrowserContext(comptime CDP_T: type) type {
|
|||||||
try self.notification.register(.http_response_header_done, self, onHttpResponseHeadersDone);
|
try self.notification.register(.http_response_header_done, self, onHttpResponseHeadersDone);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn networkDisable(self: *Self) void {
|
pub fn networkDisable(self: *BrowserContext) void {
|
||||||
self.notification.unregister(.http_request_fail, self);
|
self.notification.unregister(.http_request_fail, self);
|
||||||
self.notification.unregister(.http_request_start, self);
|
self.notification.unregister(.http_request_start, self);
|
||||||
self.notification.unregister(.http_request_done, self);
|
self.notification.unregister(.http_request_done, self);
|
||||||
@@ -557,83 +554,83 @@ pub fn BrowserContext(comptime CDP_T: type) type {
|
|||||||
self.notification.unregister(.http_response_header_done, self);
|
self.notification.unregister(.http_response_header_done, self);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn fetchEnable(self: *Self, authRequests: bool) !void {
|
pub fn fetchEnable(self: *BrowserContext, authRequests: bool) !void {
|
||||||
try self.notification.register(.http_request_intercept, self, onHttpRequestIntercept);
|
try self.notification.register(.http_request_intercept, self, onHttpRequestIntercept);
|
||||||
if (authRequests) {
|
if (authRequests) {
|
||||||
try self.notification.register(.http_request_auth_required, self, onHttpRequestAuthRequired);
|
try self.notification.register(.http_request_auth_required, self, onHttpRequestAuthRequired);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn fetchDisable(self: *Self) void {
|
pub fn fetchDisable(self: *BrowserContext) void {
|
||||||
self.notification.unregister(.http_request_intercept, self);
|
self.notification.unregister(.http_request_intercept, self);
|
||||||
self.notification.unregister(.http_request_auth_required, self);
|
self.notification.unregister(.http_request_auth_required, self);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn lifecycleEventsEnable(self: *Self) !void {
|
pub fn lifecycleEventsEnable(self: *BrowserContext) !void {
|
||||||
self.page_life_cycle_events = true;
|
self.page_life_cycle_events = true;
|
||||||
try self.notification.register(.page_network_idle, self, onPageNetworkIdle);
|
try self.notification.register(.page_network_idle, self, onPageNetworkIdle);
|
||||||
try self.notification.register(.page_network_almost_idle, self, onPageNetworkAlmostIdle);
|
try self.notification.register(.page_network_almost_idle, self, onPageNetworkAlmostIdle);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn lifecycleEventsDisable(self: *Self) void {
|
pub fn lifecycleEventsDisable(self: *BrowserContext) void {
|
||||||
self.page_life_cycle_events = false;
|
self.page_life_cycle_events = false;
|
||||||
self.notification.unregister(.page_network_idle, self);
|
self.notification.unregister(.page_network_idle, self);
|
||||||
self.notification.unregister(.page_network_almost_idle, self);
|
self.notification.unregister(.page_network_almost_idle, self);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn onPageRemove(ctx: *anyopaque, _: Notification.PageRemove) !void {
|
pub fn onPageRemove(ctx: *anyopaque, _: Notification.PageRemove) !void {
|
||||||
const self: *Self = @ptrCast(@alignCast(ctx));
|
const self: *BrowserContext = @ptrCast(@alignCast(ctx));
|
||||||
try @import("domains/page.zig").pageRemove(self);
|
try @import("domains/page.zig").pageRemove(self);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn onPageCreated(ctx: *anyopaque, page: *Page) !void {
|
pub fn onPageCreated(ctx: *anyopaque, page: *Page) !void {
|
||||||
const self: *Self = @ptrCast(@alignCast(ctx));
|
const self: *BrowserContext = @ptrCast(@alignCast(ctx));
|
||||||
return @import("domains/page.zig").pageCreated(self, page);
|
return @import("domains/page.zig").pageCreated(self, page);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn onPageNavigate(ctx: *anyopaque, msg: *const Notification.PageNavigate) !void {
|
pub fn onPageNavigate(ctx: *anyopaque, msg: *const Notification.PageNavigate) !void {
|
||||||
const self: *Self = @ptrCast(@alignCast(ctx));
|
const self: *BrowserContext = @ptrCast(@alignCast(ctx));
|
||||||
return @import("domains/page.zig").pageNavigate(self, msg);
|
return @import("domains/page.zig").pageNavigate(self, msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn onPageNavigated(ctx: *anyopaque, msg: *const Notification.PageNavigated) !void {
|
pub fn onPageNavigated(ctx: *anyopaque, msg: *const Notification.PageNavigated) !void {
|
||||||
const self: *Self = @ptrCast(@alignCast(ctx));
|
const self: *BrowserContext = @ptrCast(@alignCast(ctx));
|
||||||
defer self.resetNotificationArena();
|
defer self.resetNotificationArena();
|
||||||
return @import("domains/page.zig").pageNavigated(self.notification_arena, self, msg);
|
return @import("domains/page.zig").pageNavigated(self.notification_arena, self, msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn onPageFrameCreated(ctx: *anyopaque, msg: *const Notification.PageFrameCreated) !void {
|
pub fn onPageFrameCreated(ctx: *anyopaque, msg: *const Notification.PageFrameCreated) !void {
|
||||||
const self: *Self = @ptrCast(@alignCast(ctx));
|
const self: *BrowserContext = @ptrCast(@alignCast(ctx));
|
||||||
return @import("domains/page.zig").pageFrameCreated(self, msg);
|
return @import("domains/page.zig").pageFrameCreated(self, msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn onPageNetworkIdle(ctx: *anyopaque, msg: *const Notification.PageNetworkIdle) !void {
|
pub fn onPageNetworkIdle(ctx: *anyopaque, msg: *const Notification.PageNetworkIdle) !void {
|
||||||
const self: *Self = @ptrCast(@alignCast(ctx));
|
const self: *BrowserContext = @ptrCast(@alignCast(ctx));
|
||||||
return @import("domains/page.zig").pageNetworkIdle(self, msg);
|
return @import("domains/page.zig").pageNetworkIdle(self, msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn onPageNetworkAlmostIdle(ctx: *anyopaque, msg: *const Notification.PageNetworkAlmostIdle) !void {
|
pub fn onPageNetworkAlmostIdle(ctx: *anyopaque, msg: *const Notification.PageNetworkAlmostIdle) !void {
|
||||||
const self: *Self = @ptrCast(@alignCast(ctx));
|
const self: *BrowserContext = @ptrCast(@alignCast(ctx));
|
||||||
return @import("domains/page.zig").pageNetworkAlmostIdle(self, msg);
|
return @import("domains/page.zig").pageNetworkAlmostIdle(self, msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn onHttpRequestStart(ctx: *anyopaque, msg: *const Notification.RequestStart) !void {
|
pub fn onHttpRequestStart(ctx: *anyopaque, msg: *const Notification.RequestStart) !void {
|
||||||
const self: *Self = @ptrCast(@alignCast(ctx));
|
const self: *BrowserContext = @ptrCast(@alignCast(ctx));
|
||||||
try @import("domains/network.zig").httpRequestStart(self, msg);
|
try @import("domains/network.zig").httpRequestStart(self, msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn onHttpRequestIntercept(ctx: *anyopaque, msg: *const Notification.RequestIntercept) !void {
|
pub fn onHttpRequestIntercept(ctx: *anyopaque, msg: *const Notification.RequestIntercept) !void {
|
||||||
const self: *Self = @ptrCast(@alignCast(ctx));
|
const self: *BrowserContext = @ptrCast(@alignCast(ctx));
|
||||||
try @import("domains/fetch.zig").requestIntercept(self, msg);
|
try @import("domains/fetch.zig").requestIntercept(self, msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn onHttpRequestFail(ctx: *anyopaque, msg: *const Notification.RequestFail) !void {
|
pub fn onHttpRequestFail(ctx: *anyopaque, msg: *const Notification.RequestFail) !void {
|
||||||
const self: *Self = @ptrCast(@alignCast(ctx));
|
const self: *BrowserContext = @ptrCast(@alignCast(ctx));
|
||||||
return @import("domains/network.zig").httpRequestFail(self, msg);
|
return @import("domains/network.zig").httpRequestFail(self, msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn onHttpResponseHeadersDone(ctx: *anyopaque, msg: *const Notification.ResponseHeaderDone) !void {
|
pub fn onHttpResponseHeadersDone(ctx: *anyopaque, msg: *const Notification.ResponseHeaderDone) !void {
|
||||||
const self: *Self = @ptrCast(@alignCast(ctx));
|
const self: *BrowserContext = @ptrCast(@alignCast(ctx));
|
||||||
defer self.resetNotificationArena();
|
defer self.resetNotificationArena();
|
||||||
|
|
||||||
const arena = self.page_arena;
|
const arena = self.page_arena;
|
||||||
@@ -668,12 +665,12 @@ pub fn BrowserContext(comptime CDP_T: type) type {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn onHttpRequestDone(ctx: *anyopaque, msg: *const Notification.RequestDone) !void {
|
pub fn onHttpRequestDone(ctx: *anyopaque, msg: *const Notification.RequestDone) !void {
|
||||||
const self: *Self = @ptrCast(@alignCast(ctx));
|
const self: *BrowserContext = @ptrCast(@alignCast(ctx));
|
||||||
return @import("domains/network.zig").httpRequestDone(self, msg);
|
return @import("domains/network.zig").httpRequestDone(self, msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn onHttpResponseData(ctx: *anyopaque, msg: *const Notification.ResponseData) !void {
|
pub fn onHttpResponseData(ctx: *anyopaque, msg: *const Notification.ResponseData) !void {
|
||||||
const self: *Self = @ptrCast(@alignCast(ctx));
|
const self: *BrowserContext = @ptrCast(@alignCast(ctx));
|
||||||
const arena = self.page_arena;
|
const arena = self.page_arena;
|
||||||
|
|
||||||
const id = msg.transfer.id;
|
const id = msg.transfer.id;
|
||||||
@@ -683,16 +680,16 @@ pub fn BrowserContext(comptime CDP_T: type) type {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn onHttpRequestAuthRequired(ctx: *anyopaque, data: *const Notification.RequestAuthRequired) !void {
|
pub fn onHttpRequestAuthRequired(ctx: *anyopaque, data: *const Notification.RequestAuthRequired) !void {
|
||||||
const self: *Self = @ptrCast(@alignCast(ctx));
|
const self: *BrowserContext = @ptrCast(@alignCast(ctx));
|
||||||
defer self.resetNotificationArena();
|
defer self.resetNotificationArena();
|
||||||
try @import("domains/fetch.zig").requestAuthRequired(self, data);
|
try @import("domains/fetch.zig").requestAuthRequired(self, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn resetNotificationArena(self: *Self) void {
|
fn resetNotificationArena(self: *BrowserContext) void {
|
||||||
defer _ = self.cdp.notification_arena.reset(.{ .retain_with_limit = 1024 * 64 });
|
defer _ = self.cdp.notification_arena.reset(.{ .retain_with_limit = 1024 * 64 });
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn callInspector(self: *const Self, msg: []const u8) void {
|
pub fn callInspector(self: *const BrowserContext, msg: []const u8) void {
|
||||||
self.inspector_session.send(msg);
|
self.inspector_session.send(msg);
|
||||||
self.session.browser.env.runMicrotasks();
|
self.session.browser.env.runMicrotasks();
|
||||||
}
|
}
|
||||||
@@ -723,7 +720,7 @@ pub fn BrowserContext(comptime CDP_T: type) type {
|
|||||||
// This is hacky x 2. First, we create the JSON payload by gluing our
|
// This is hacky x 2. First, we create the JSON payload by gluing our
|
||||||
// session_id onto it. Second, we're much more client/websocket aware than
|
// session_id onto it. Second, we're much more client/websocket aware than
|
||||||
// we should be.
|
// we should be.
|
||||||
fn sendInspectorMessage(self: *Self, msg: []const u8) !void {
|
fn sendInspectorMessage(self: *BrowserContext, msg: []const u8) !void {
|
||||||
const session_id = self.session_id orelse {
|
const session_id = self.session_id orelse {
|
||||||
// We no longer have an active session. What should we do
|
// We no longer have an active session. What should we do
|
||||||
// in this case?
|
// in this case?
|
||||||
@@ -759,8 +756,7 @@ pub fn BrowserContext(comptime CDP_T: type) type {
|
|||||||
|
|
||||||
try cdp.client.sendJSONRaw(buf);
|
try cdp.client.sendJSONRaw(buf);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
|
||||||
|
|
||||||
/// see: https://chromium.googlesource.com/chromium/src/+/master/third_party/blink/renderer/bindings/core/v8/V8BindingDesign.md#world
|
/// see: https://chromium.googlesource.com/chromium/src/+/master/third_party/blink/renderer/bindings/core/v8/V8BindingDesign.md#world
|
||||||
/// The current understanding. An isolated world lives in the same isolate, but a separated context.
|
/// The current understanding. An isolated world lives in the same isolate, but a separated context.
|
||||||
@@ -832,17 +828,16 @@ const IsolatedWorld = struct {
|
|||||||
// behaviors. Normally, we're sending the result to the client. But in some cases
|
// behaviors. Normally, we're sending the result to the client. But in some cases
|
||||||
// we want to capture the result. So we want the command.sendResult to be
|
// we want to capture the result. So we want the command.sendResult to be
|
||||||
// generic.
|
// generic.
|
||||||
pub fn Command(comptime CDP_T: type, comptime Sender: type) type {
|
pub const Command = struct {
|
||||||
return struct {
|
|
||||||
// A misc arena that can be used for any allocation for processing
|
// A misc arena that can be used for any allocation for processing
|
||||||
// the message
|
// the message
|
||||||
arena: Allocator,
|
arena: Allocator,
|
||||||
|
|
||||||
// reference to our CDP instance
|
// reference to our CDP instance
|
||||||
cdp: *CDP_T,
|
cdp: *CDP,
|
||||||
|
|
||||||
// The browser context this command targets
|
// The browser context this command targets
|
||||||
browser_context: ?*BrowserContext(CDP_T),
|
browser_context: ?*BrowserContext,
|
||||||
|
|
||||||
// The command input (the id, optional session_id, params, ...)
|
// The command input (the id, optional session_id, params, ...)
|
||||||
input: Input,
|
input: Input,
|
||||||
@@ -853,9 +848,23 @@ pub fn Command(comptime CDP_T: type, comptime Sender: type) type {
|
|||||||
// be code to capture the data that we were "sending".
|
// be code to capture the data that we were "sending".
|
||||||
sender: Sender,
|
sender: Sender,
|
||||||
|
|
||||||
const Self = @This();
|
const Sender = union(enum) {
|
||||||
|
cdp: *CDP,
|
||||||
|
capture: *std.Io.Writer,
|
||||||
|
|
||||||
pub fn params(self: *const Self, comptime T: type) !?T {
|
pub fn sendJSON(self: Sender, message: anytype) !void {
|
||||||
|
switch (self) {
|
||||||
|
.cdp => |cdp| return cdp.sendJSON(message),
|
||||||
|
.capture => |writer| {
|
||||||
|
return std.json.Stringify.value(message, .{
|
||||||
|
.emit_null_optional_fields = false,
|
||||||
|
}, writer);
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
pub fn params(self: *const Command, comptime T: type) !?T {
|
||||||
if (self.input.params) |p| {
|
if (self.input.params) |p| {
|
||||||
return try json.parseFromSliceLeaky(
|
return try json.parseFromSliceLeaky(
|
||||||
T,
|
T,
|
||||||
@@ -867,7 +876,7 @@ pub fn Command(comptime CDP_T: type, comptime Sender: type) type {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn createBrowserContext(self: *Self) !*BrowserContext(CDP_T) {
|
pub fn createBrowserContext(self: *Command) !*BrowserContext {
|
||||||
_ = try self.cdp.createBrowserContext();
|
_ = try self.cdp.createBrowserContext();
|
||||||
self.browser_context = &(self.cdp.browser_context.?);
|
self.browser_context = &(self.cdp.browser_context.?);
|
||||||
return self.browser_context.?;
|
return self.browser_context.?;
|
||||||
@@ -876,7 +885,7 @@ pub fn Command(comptime CDP_T: type, comptime Sender: type) type {
|
|||||||
const SendResultOpts = struct {
|
const SendResultOpts = struct {
|
||||||
include_session_id: bool = true,
|
include_session_id: bool = true,
|
||||||
};
|
};
|
||||||
pub fn sendResult(self: *Self, result: anytype, opts: SendResultOpts) !void {
|
pub fn sendResult(self: *Command, result: anytype, opts: SendResultOpts) !void {
|
||||||
return self.sender.sendJSON(.{
|
return self.sender.sendJSON(.{
|
||||||
.id = self.input.id,
|
.id = self.input.id,
|
||||||
.result = if (comptime @typeInfo(@TypeOf(result)) == .null) struct {}{} else result,
|
.result = if (comptime @typeInfo(@TypeOf(result)) == .null) struct {}{} else result,
|
||||||
@@ -884,10 +893,7 @@ pub fn Command(comptime CDP_T: type, comptime Sender: type) type {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
const SendEventOpts = struct {
|
pub fn sendEvent(self: *Command, method: []const u8, p: anytype, opts: SendEventOpts) !void {
|
||||||
session_id: ?[]const u8 = null,
|
|
||||||
};
|
|
||||||
pub fn sendEvent(self: *Self, method: []const u8, p: anytype, opts: CDP_T.SendEventOpts) !void {
|
|
||||||
// Events ALWAYS go to the client. self.sender should not be used
|
// Events ALWAYS go to the client. self.sender should not be used
|
||||||
return self.cdp.sendEvent(method, p, opts);
|
return self.cdp.sendEvent(method, p, opts);
|
||||||
}
|
}
|
||||||
@@ -895,7 +901,7 @@ pub fn Command(comptime CDP_T: type, comptime Sender: type) type {
|
|||||||
const SendErrorOpts = struct {
|
const SendErrorOpts = struct {
|
||||||
include_session_id: bool = true,
|
include_session_id: bool = true,
|
||||||
};
|
};
|
||||||
pub fn sendError(self: *Self, code: i32, message: []const u8, opts: SendErrorOpts) !void {
|
pub fn sendError(self: *Command, code: i32, message: []const u8, opts: SendErrorOpts) !void {
|
||||||
return self.sender.sendJSON(.{
|
return self.sender.sendJSON(.{
|
||||||
.id = self.input.id,
|
.id = self.input.id,
|
||||||
.@"error" = .{ .code = code, .message = message },
|
.@"error" = .{ .code = code, .message = message },
|
||||||
@@ -920,8 +926,7 @@ pub fn Command(comptime CDP_T: type, comptime Sender: type) type {
|
|||||||
// The full raw json input
|
// The full raw json input
|
||||||
json: []const u8,
|
json: []const u8,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
}
|
|
||||||
|
|
||||||
// When we parse a JSON message from the client, this is the structure
|
// When we parse a JSON message from the client, this is the structure
|
||||||
// we always expect
|
// we always expect
|
||||||
|
|||||||
@@ -18,8 +18,9 @@
|
|||||||
|
|
||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
const id = @import("../id.zig");
|
const id = @import("../id.zig");
|
||||||
|
const CDP = @import("../CDP.zig");
|
||||||
|
|
||||||
pub fn processMessage(cmd: anytype) !void {
|
pub fn processMessage(cmd: *CDP.Command) !void {
|
||||||
const action = std.meta.stringToEnum(enum {
|
const action = std.meta.stringToEnum(enum {
|
||||||
enable,
|
enable,
|
||||||
disable,
|
disable,
|
||||||
@@ -32,15 +33,15 @@ pub fn processMessage(cmd: anytype) !void {
|
|||||||
.getFullAXTree => return getFullAXTree(cmd),
|
.getFullAXTree => return getFullAXTree(cmd),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn enable(cmd: anytype) !void {
|
fn enable(cmd: *CDP.Command) !void {
|
||||||
return cmd.sendResult(null, .{});
|
return cmd.sendResult(null, .{});
|
||||||
}
|
}
|
||||||
|
|
||||||
fn disable(cmd: anytype) !void {
|
fn disable(cmd: *CDP.Command) !void {
|
||||||
return cmd.sendResult(null, .{});
|
return cmd.sendResult(null, .{});
|
||||||
}
|
}
|
||||||
|
|
||||||
fn getFullAXTree(cmd: anytype) !void {
|
fn getFullAXTree(cmd: *CDP.Command) !void {
|
||||||
const params = (try cmd.params(struct {
|
const params = (try cmd.params(struct {
|
||||||
depth: ?i32 = null,
|
depth: ?i32 = null,
|
||||||
frameId: ?[]const u8 = null,
|
frameId: ?[]const u8 = null,
|
||||||
|
|||||||
@@ -17,6 +17,7 @@
|
|||||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
|
const CDP = @import("../CDP.zig");
|
||||||
|
|
||||||
// TODO: hard coded data
|
// TODO: hard coded data
|
||||||
const PROTOCOL_VERSION = "1.3";
|
const PROTOCOL_VERSION = "1.3";
|
||||||
@@ -35,7 +36,7 @@ const PRODUCT = "Chrome/124.0.6367.29";
|
|||||||
const JS_VERSION = "12.4.254.8";
|
const JS_VERSION = "12.4.254.8";
|
||||||
const DEV_TOOLS_WINDOW_ID = 1923710101;
|
const DEV_TOOLS_WINDOW_ID = 1923710101;
|
||||||
|
|
||||||
pub fn processMessage(cmd: anytype) !void {
|
pub fn processMessage(cmd: *CDP.Command) !void {
|
||||||
const action = std.meta.stringToEnum(enum {
|
const action = std.meta.stringToEnum(enum {
|
||||||
getVersion,
|
getVersion,
|
||||||
setPermission,
|
setPermission,
|
||||||
@@ -57,7 +58,7 @@ pub fn processMessage(cmd: anytype) !void {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn getVersion(cmd: anytype) !void {
|
fn getVersion(cmd: *CDP.Command) !void {
|
||||||
// TODO: pre-serialize?
|
// TODO: pre-serialize?
|
||||||
return cmd.sendResult(.{
|
return cmd.sendResult(.{
|
||||||
.protocolVersion = PROTOCOL_VERSION,
|
.protocolVersion = PROTOCOL_VERSION,
|
||||||
@@ -69,7 +70,7 @@ fn getVersion(cmd: anytype) !void {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// TODO: noop method
|
// TODO: noop method
|
||||||
fn setDownloadBehavior(cmd: anytype) !void {
|
fn setDownloadBehavior(cmd: *CDP.Command) !void {
|
||||||
// const params = (try cmd.params(struct {
|
// const params = (try cmd.params(struct {
|
||||||
// behavior: []const u8,
|
// behavior: []const u8,
|
||||||
// browserContextId: ?[]const u8 = null,
|
// browserContextId: ?[]const u8 = null,
|
||||||
@@ -80,7 +81,7 @@ fn setDownloadBehavior(cmd: anytype) !void {
|
|||||||
return cmd.sendResult(null, .{ .include_session_id = false });
|
return cmd.sendResult(null, .{ .include_session_id = false });
|
||||||
}
|
}
|
||||||
|
|
||||||
fn getWindowForTarget(cmd: anytype) !void {
|
fn getWindowForTarget(cmd: *CDP.Command) !void {
|
||||||
// const params = (try cmd.params(struct {
|
// const params = (try cmd.params(struct {
|
||||||
// targetId: ?[]const u8 = null,
|
// targetId: ?[]const u8 = null,
|
||||||
// })) orelse return error.InvalidParams;
|
// })) orelse return error.InvalidParams;
|
||||||
@@ -91,22 +92,22 @@ fn getWindowForTarget(cmd: anytype) !void {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// TODO: noop method
|
// TODO: noop method
|
||||||
fn setWindowBounds(cmd: anytype) !void {
|
fn setWindowBounds(cmd: *CDP.Command) !void {
|
||||||
return cmd.sendResult(null, .{});
|
return cmd.sendResult(null, .{});
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: noop method
|
// TODO: noop method
|
||||||
fn grantPermissions(cmd: anytype) !void {
|
fn grantPermissions(cmd: *CDP.Command) !void {
|
||||||
return cmd.sendResult(null, .{});
|
return cmd.sendResult(null, .{});
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: noop method
|
// TODO: noop method
|
||||||
fn setPermission(cmd: anytype) !void {
|
fn setPermission(cmd: *CDP.Command) !void {
|
||||||
return cmd.sendResult(null, .{});
|
return cmd.sendResult(null, .{});
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: noop method
|
// TODO: noop method
|
||||||
fn resetPermissions(cmd: anytype) !void {
|
fn resetPermissions(cmd: *CDP.Command) !void {
|
||||||
return cmd.sendResult(null, .{});
|
return cmd.sendResult(null, .{});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -17,8 +17,9 @@
|
|||||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
|
const CDP = @import("../CDP.zig");
|
||||||
|
|
||||||
pub fn processMessage(cmd: anytype) !void {
|
pub fn processMessage(cmd: *CDP.Command) !void {
|
||||||
const action = std.meta.stringToEnum(enum {
|
const action = std.meta.stringToEnum(enum {
|
||||||
enable,
|
enable,
|
||||||
}, cmd.input.action) orelse return error.UnknownMethod;
|
}, cmd.input.action) orelse return error.UnknownMethod;
|
||||||
|
|||||||
@@ -18,17 +18,18 @@
|
|||||||
|
|
||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
const id = @import("../id.zig");
|
const id = @import("../id.zig");
|
||||||
const log = @import("../../log.zig");
|
const CDP = @import("../CDP.zig");
|
||||||
const Node = @import("../Node.zig");
|
const Node = @import("../Node.zig");
|
||||||
|
|
||||||
|
const log = @import("../../log.zig");
|
||||||
|
const dump = @import("../../browser/dump.zig");
|
||||||
|
const js = @import("../../browser/js/js.zig");
|
||||||
const DOMNode = @import("../../browser/webapi/Node.zig");
|
const DOMNode = @import("../../browser/webapi/Node.zig");
|
||||||
const Selector = @import("../../browser/webapi/selector/Selector.zig");
|
const Selector = @import("../../browser/webapi/selector/Selector.zig");
|
||||||
|
|
||||||
const dump = @import("../../browser/dump.zig");
|
|
||||||
const js = @import("../../browser/js/js.zig");
|
|
||||||
|
|
||||||
const Allocator = std.mem.Allocator;
|
const Allocator = std.mem.Allocator;
|
||||||
|
|
||||||
pub fn processMessage(cmd: anytype) !void {
|
pub fn processMessage(cmd: *CDP.Command) !void {
|
||||||
const action = std.meta.stringToEnum(enum {
|
const action = std.meta.stringToEnum(enum {
|
||||||
enable,
|
enable,
|
||||||
getDocument,
|
getDocument,
|
||||||
@@ -69,7 +70,7 @@ pub fn processMessage(cmd: anytype) !void {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// https://chromedevtools.github.io/devtools-protocol/tot/DOM/#method-getDocument
|
// https://chromedevtools.github.io/devtools-protocol/tot/DOM/#method-getDocument
|
||||||
fn getDocument(cmd: anytype) !void {
|
fn getDocument(cmd: *CDP.Command) !void {
|
||||||
const Params = struct {
|
const Params = struct {
|
||||||
// CDP documentation implies that 0 isn't valid, but it _does_ work in Chrome
|
// CDP documentation implies that 0 isn't valid, but it _does_ work in Chrome
|
||||||
depth: i32 = 3,
|
depth: i32 = 3,
|
||||||
@@ -89,7 +90,7 @@ fn getDocument(cmd: anytype) !void {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// https://chromedevtools.github.io/devtools-protocol/tot/DOM/#method-performSearch
|
// https://chromedevtools.github.io/devtools-protocol/tot/DOM/#method-performSearch
|
||||||
fn performSearch(cmd: anytype) !void {
|
fn performSearch(cmd: *CDP.Command) !void {
|
||||||
const params = (try cmd.params(struct {
|
const params = (try cmd.params(struct {
|
||||||
query: []const u8,
|
query: []const u8,
|
||||||
includeUserAgentShadowDOM: ?bool = null,
|
includeUserAgentShadowDOM: ?bool = null,
|
||||||
@@ -116,7 +117,7 @@ fn performSearch(cmd: anytype) !void {
|
|||||||
// hierarchy of each nodes.
|
// hierarchy of each nodes.
|
||||||
// We dispatch event in the reverse order: from the top level to the direct parents.
|
// We dispatch event in the reverse order: from the top level to the direct parents.
|
||||||
// We should dispatch a node only if it has never been sent.
|
// We should dispatch a node only if it has never been sent.
|
||||||
fn dispatchSetChildNodes(cmd: anytype, dom_nodes: []const *DOMNode) !void {
|
fn dispatchSetChildNodes(cmd: *CDP.Command, dom_nodes: []const *DOMNode) !void {
|
||||||
const arena = cmd.arena;
|
const arena = cmd.arena;
|
||||||
const bc = cmd.browser_context orelse return error.BrowserContextNotLoaded;
|
const bc = cmd.browser_context orelse return error.BrowserContextNotLoaded;
|
||||||
const session_id = bc.session_id orelse return error.SessionIdNotLoaded;
|
const session_id = bc.session_id orelse return error.SessionIdNotLoaded;
|
||||||
@@ -172,7 +173,7 @@ fn dispatchSetChildNodes(cmd: anytype, dom_nodes: []const *DOMNode) !void {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// https://chromedevtools.github.io/devtools-protocol/tot/DOM/#method-discardSearchResults
|
// https://chromedevtools.github.io/devtools-protocol/tot/DOM/#method-discardSearchResults
|
||||||
fn discardSearchResults(cmd: anytype) !void {
|
fn discardSearchResults(cmd: *CDP.Command) !void {
|
||||||
const params = (try cmd.params(struct {
|
const params = (try cmd.params(struct {
|
||||||
searchId: []const u8,
|
searchId: []const u8,
|
||||||
})) orelse return error.InvalidParams;
|
})) orelse return error.InvalidParams;
|
||||||
@@ -184,7 +185,7 @@ fn discardSearchResults(cmd: anytype) !void {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// https://chromedevtools.github.io/devtools-protocol/tot/DOM/#method-getSearchResults
|
// https://chromedevtools.github.io/devtools-protocol/tot/DOM/#method-getSearchResults
|
||||||
fn getSearchResults(cmd: anytype) !void {
|
fn getSearchResults(cmd: *CDP.Command) !void {
|
||||||
const params = (try cmd.params(struct {
|
const params = (try cmd.params(struct {
|
||||||
searchId: []const u8,
|
searchId: []const u8,
|
||||||
fromIndex: u32,
|
fromIndex: u32,
|
||||||
@@ -209,7 +210,7 @@ fn getSearchResults(cmd: anytype) !void {
|
|||||||
return cmd.sendResult(.{ .nodeIds = node_ids[params.fromIndex..params.toIndex] }, .{});
|
return cmd.sendResult(.{ .nodeIds = node_ids[params.fromIndex..params.toIndex] }, .{});
|
||||||
}
|
}
|
||||||
|
|
||||||
fn querySelector(cmd: anytype) !void {
|
fn querySelector(cmd: *CDP.Command) !void {
|
||||||
const params = (try cmd.params(struct {
|
const params = (try cmd.params(struct {
|
||||||
nodeId: Node.Id,
|
nodeId: Node.Id,
|
||||||
selector: []const u8,
|
selector: []const u8,
|
||||||
@@ -235,7 +236,7 @@ fn querySelector(cmd: anytype) !void {
|
|||||||
}, .{});
|
}, .{});
|
||||||
}
|
}
|
||||||
|
|
||||||
fn querySelectorAll(cmd: anytype) !void {
|
fn querySelectorAll(cmd: *CDP.Command) !void {
|
||||||
const params = (try cmd.params(struct {
|
const params = (try cmd.params(struct {
|
||||||
nodeId: Node.Id,
|
nodeId: Node.Id,
|
||||||
selector: []const u8,
|
selector: []const u8,
|
||||||
@@ -266,7 +267,7 @@ fn querySelectorAll(cmd: anytype) !void {
|
|||||||
}, .{});
|
}, .{});
|
||||||
}
|
}
|
||||||
|
|
||||||
fn resolveNode(cmd: anytype) !void {
|
fn resolveNode(cmd: *CDP.Command) !void {
|
||||||
const params = (try cmd.params(struct {
|
const params = (try cmd.params(struct {
|
||||||
nodeId: ?Node.Id = null,
|
nodeId: ?Node.Id = null,
|
||||||
backendNodeId: ?u32 = null,
|
backendNodeId: ?u32 = null,
|
||||||
@@ -327,7 +328,7 @@ fn resolveNode(cmd: anytype) !void {
|
|||||||
} }, .{});
|
} }, .{});
|
||||||
}
|
}
|
||||||
|
|
||||||
fn describeNode(cmd: anytype) !void {
|
fn describeNode(cmd: *CDP.Command) !void {
|
||||||
const params = (try cmd.params(struct {
|
const params = (try cmd.params(struct {
|
||||||
nodeId: ?Node.Id = null,
|
nodeId: ?Node.Id = null,
|
||||||
backendNodeId: ?Node.Id = null,
|
backendNodeId: ?Node.Id = null,
|
||||||
@@ -374,7 +375,7 @@ fn rectToQuad(rect: DOMNode.Element.DOMRect) Quad {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
fn scrollIntoViewIfNeeded(cmd: anytype) !void {
|
fn scrollIntoViewIfNeeded(cmd: *CDP.Command) !void {
|
||||||
const params = (try cmd.params(struct {
|
const params = (try cmd.params(struct {
|
||||||
nodeId: ?Node.Id = null,
|
nodeId: ?Node.Id = null,
|
||||||
backendNodeId: ?u32 = null,
|
backendNodeId: ?u32 = null,
|
||||||
@@ -397,7 +398,7 @@ fn scrollIntoViewIfNeeded(cmd: anytype) !void {
|
|||||||
return cmd.sendResult(null, .{});
|
return cmd.sendResult(null, .{});
|
||||||
}
|
}
|
||||||
|
|
||||||
fn getNode(arena: Allocator, bc: anytype, node_id: ?Node.Id, backend_node_id: ?Node.Id, object_id: ?[]const u8) !*Node {
|
fn getNode(arena: Allocator, bc: *CDP.BrowserContext, node_id: ?Node.Id, backend_node_id: ?Node.Id, object_id: ?[]const u8) !*Node {
|
||||||
const input_node_id = node_id orelse backend_node_id;
|
const input_node_id = node_id orelse backend_node_id;
|
||||||
if (input_node_id) |input_node_id_| {
|
if (input_node_id) |input_node_id_| {
|
||||||
return bc.node_registry.lookup_by_id.get(input_node_id_) orelse return error.NodeNotFound;
|
return bc.node_registry.lookup_by_id.get(input_node_id_) orelse return error.NodeNotFound;
|
||||||
@@ -417,7 +418,7 @@ fn getNode(arena: Allocator, bc: anytype, node_id: ?Node.Id, backend_node_id: ?N
|
|||||||
|
|
||||||
// https://chromedevtools.github.io/devtools-protocol/tot/DOM/#method-getContentQuads
|
// https://chromedevtools.github.io/devtools-protocol/tot/DOM/#method-getContentQuads
|
||||||
// Related to: https://drafts.csswg.org/cssom-view/#the-geometryutils-interface
|
// Related to: https://drafts.csswg.org/cssom-view/#the-geometryutils-interface
|
||||||
fn getContentQuads(cmd: anytype) !void {
|
fn getContentQuads(cmd: *CDP.Command) !void {
|
||||||
const params = (try cmd.params(struct {
|
const params = (try cmd.params(struct {
|
||||||
nodeId: ?Node.Id = null,
|
nodeId: ?Node.Id = null,
|
||||||
backendNodeId: ?Node.Id = null,
|
backendNodeId: ?Node.Id = null,
|
||||||
@@ -443,7 +444,7 @@ fn getContentQuads(cmd: anytype) !void {
|
|||||||
return cmd.sendResult(.{ .quads = &.{quad} }, .{});
|
return cmd.sendResult(.{ .quads = &.{quad} }, .{});
|
||||||
}
|
}
|
||||||
|
|
||||||
fn getBoxModel(cmd: anytype) !void {
|
fn getBoxModel(cmd: *CDP.Command) !void {
|
||||||
const params = (try cmd.params(struct {
|
const params = (try cmd.params(struct {
|
||||||
nodeId: ?Node.Id = null,
|
nodeId: ?Node.Id = null,
|
||||||
backendNodeId: ?u32 = null,
|
backendNodeId: ?u32 = null,
|
||||||
@@ -472,7 +473,7 @@ fn getBoxModel(cmd: anytype) !void {
|
|||||||
} }, .{});
|
} }, .{});
|
||||||
}
|
}
|
||||||
|
|
||||||
fn requestChildNodes(cmd: anytype) !void {
|
fn requestChildNodes(cmd: *CDP.Command) !void {
|
||||||
const params = (try cmd.params(struct {
|
const params = (try cmd.params(struct {
|
||||||
nodeId: Node.Id,
|
nodeId: Node.Id,
|
||||||
depth: i32 = 1,
|
depth: i32 = 1,
|
||||||
@@ -496,7 +497,7 @@ fn requestChildNodes(cmd: anytype) !void {
|
|||||||
return cmd.sendResult(null, .{});
|
return cmd.sendResult(null, .{});
|
||||||
}
|
}
|
||||||
|
|
||||||
fn getFrameOwner(cmd: anytype) !void {
|
fn getFrameOwner(cmd: *CDP.Command) !void {
|
||||||
const params = (try cmd.params(struct {
|
const params = (try cmd.params(struct {
|
||||||
frameId: []const u8,
|
frameId: []const u8,
|
||||||
})) orelse return error.InvalidParams;
|
})) orelse return error.InvalidParams;
|
||||||
@@ -512,7 +513,7 @@ fn getFrameOwner(cmd: anytype) !void {
|
|||||||
return cmd.sendResult(.{ .nodeId = node.id, .backendNodeId = node.id }, .{});
|
return cmd.sendResult(.{ .nodeId = node.id, .backendNodeId = node.id }, .{});
|
||||||
}
|
}
|
||||||
|
|
||||||
fn getOuterHTML(cmd: anytype) !void {
|
fn getOuterHTML(cmd: *CDP.Command) !void {
|
||||||
const params = (try cmd.params(struct {
|
const params = (try cmd.params(struct {
|
||||||
nodeId: ?Node.Id = null,
|
nodeId: ?Node.Id = null,
|
||||||
backendNodeId: ?Node.Id = null,
|
backendNodeId: ?Node.Id = null,
|
||||||
@@ -534,7 +535,7 @@ fn getOuterHTML(cmd: anytype) !void {
|
|||||||
return cmd.sendResult(.{ .outerHTML = aw.written() }, .{});
|
return cmd.sendResult(.{ .outerHTML = aw.written() }, .{});
|
||||||
}
|
}
|
||||||
|
|
||||||
fn requestNode(cmd: anytype) !void {
|
fn requestNode(cmd: *CDP.Command) !void {
|
||||||
const params = (try cmd.params(struct {
|
const params = (try cmd.params(struct {
|
||||||
objectId: []const u8,
|
objectId: []const u8,
|
||||||
})) orelse return error.InvalidParams;
|
})) orelse return error.InvalidParams;
|
||||||
|
|||||||
@@ -17,9 +17,10 @@
|
|||||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
|
const CDP = @import("../CDP.zig");
|
||||||
const log = @import("../../log.zig");
|
const log = @import("../../log.zig");
|
||||||
|
|
||||||
pub fn processMessage(cmd: anytype) !void {
|
pub fn processMessage(cmd: *CDP.Command) !void {
|
||||||
const action = std.meta.stringToEnum(enum {
|
const action = std.meta.stringToEnum(enum {
|
||||||
setEmulatedMedia,
|
setEmulatedMedia,
|
||||||
setFocusEmulationEnabled,
|
setFocusEmulationEnabled,
|
||||||
@@ -38,7 +39,7 @@ pub fn processMessage(cmd: anytype) !void {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// TODO: noop method
|
// TODO: noop method
|
||||||
fn setEmulatedMedia(cmd: anytype) !void {
|
fn setEmulatedMedia(cmd: *CDP.Command) !void {
|
||||||
// const input = (try const incoming.params(struct {
|
// const input = (try const incoming.params(struct {
|
||||||
// media: ?[]const u8 = null,
|
// media: ?[]const u8 = null,
|
||||||
// features: ?[]struct{
|
// features: ?[]struct{
|
||||||
@@ -51,7 +52,7 @@ fn setEmulatedMedia(cmd: anytype) !void {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// TODO: noop method
|
// TODO: noop method
|
||||||
fn setFocusEmulationEnabled(cmd: anytype) !void {
|
fn setFocusEmulationEnabled(cmd: *CDP.Command) !void {
|
||||||
// const input = (try const incoming.params(struct {
|
// const input = (try const incoming.params(struct {
|
||||||
// enabled: bool,
|
// enabled: bool,
|
||||||
// })) orelse return error.InvalidParams;
|
// })) orelse return error.InvalidParams;
|
||||||
@@ -59,16 +60,16 @@ fn setFocusEmulationEnabled(cmd: anytype) !void {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// TODO: noop method
|
// TODO: noop method
|
||||||
fn setDeviceMetricsOverride(cmd: anytype) !void {
|
fn setDeviceMetricsOverride(cmd: *CDP.Command) !void {
|
||||||
return cmd.sendResult(null, .{});
|
return cmd.sendResult(null, .{});
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: noop method
|
// TODO: noop method
|
||||||
fn setTouchEmulationEnabled(cmd: anytype) !void {
|
fn setTouchEmulationEnabled(cmd: *CDP.Command) !void {
|
||||||
return cmd.sendResult(null, .{});
|
return cmd.sendResult(null, .{});
|
||||||
}
|
}
|
||||||
|
|
||||||
fn setUserAgentOverride(cmd: anytype) !void {
|
fn setUserAgentOverride(cmd: *CDP.Command) !void {
|
||||||
log.info(.app, "setUserAgentOverride ignored", .{});
|
log.info(.app, "setUserAgentOverride ignored", .{});
|
||||||
return cmd.sendResult(null, .{});
|
return cmd.sendResult(null, .{});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,17 +17,19 @@
|
|||||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
const Allocator = std.mem.Allocator;
|
|
||||||
|
|
||||||
const id = @import("../id.zig");
|
const id = @import("../id.zig");
|
||||||
|
const CDP = @import("../CDP.zig");
|
||||||
const log = @import("../../log.zig");
|
const log = @import("../../log.zig");
|
||||||
const network = @import("network.zig");
|
|
||||||
|
|
||||||
const HttpClient = @import("../../browser/HttpClient.zig");
|
const HttpClient = @import("../../browser/HttpClient.zig");
|
||||||
const net_http = @import("../../network/http.zig");
|
const net_http = @import("../../network/http.zig");
|
||||||
const Notification = @import("../../Notification.zig");
|
const Notification = @import("../../Notification.zig");
|
||||||
|
|
||||||
pub fn processMessage(cmd: anytype) !void {
|
const network = @import("network.zig");
|
||||||
|
const Allocator = std.mem.Allocator;
|
||||||
|
|
||||||
|
pub fn processMessage(cmd: *CDP.Command) !void {
|
||||||
const action = std.meta.stringToEnum(enum {
|
const action = std.meta.stringToEnum(enum {
|
||||||
disable,
|
disable,
|
||||||
enable,
|
enable,
|
||||||
@@ -135,13 +137,13 @@ const ErrorReason = enum {
|
|||||||
BlockedByResponse,
|
BlockedByResponse,
|
||||||
};
|
};
|
||||||
|
|
||||||
fn disable(cmd: anytype) !void {
|
fn disable(cmd: *CDP.Command) !void {
|
||||||
const bc = cmd.browser_context orelse return error.BrowserContextNotLoaded;
|
const bc = cmd.browser_context orelse return error.BrowserContextNotLoaded;
|
||||||
bc.fetchDisable();
|
bc.fetchDisable();
|
||||||
return cmd.sendResult(null, .{});
|
return cmd.sendResult(null, .{});
|
||||||
}
|
}
|
||||||
|
|
||||||
fn enable(cmd: anytype) !void {
|
fn enable(cmd: *CDP.Command) !void {
|
||||||
const params = (try cmd.params(EnableParam)) orelse EnableParam{};
|
const params = (try cmd.params(EnableParam)) orelse EnableParam{};
|
||||||
if (!arePatternsSupported(params.patterns)) {
|
if (!arePatternsSupported(params.patterns)) {
|
||||||
log.warn(.not_implemented, "Fetch.enable", .{ .params = "pattern" });
|
log.warn(.not_implemented, "Fetch.enable", .{ .params = "pattern" });
|
||||||
@@ -180,7 +182,7 @@ fn arePatternsSupported(patterns: []RequestPattern) bool {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn requestIntercept(bc: anytype, intercept: *const Notification.RequestIntercept) !void {
|
pub fn requestIntercept(bc: *CDP.BrowserContext, intercept: *const Notification.RequestIntercept) !void {
|
||||||
// detachTarget could be called, in which case, we still have a page doing
|
// detachTarget could be called, in which case, we still have a page doing
|
||||||
// things, but no session.
|
// things, but no session.
|
||||||
const session_id = bc.session_id orelse return;
|
const session_id = bc.session_id orelse return;
|
||||||
@@ -215,7 +217,7 @@ pub fn requestIntercept(bc: anytype, intercept: *const Notification.RequestInter
|
|||||||
intercept.wait_for_interception.* = true;
|
intercept.wait_for_interception.* = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn continueRequest(cmd: anytype) !void {
|
fn continueRequest(cmd: *CDP.Command) !void {
|
||||||
const bc = cmd.browser_context orelse return error.BrowserContextNotLoaded;
|
const bc = cmd.browser_context orelse return error.BrowserContextNotLoaded;
|
||||||
const params = (try cmd.params(struct {
|
const params = (try cmd.params(struct {
|
||||||
requestId: []const u8, // INT-{d}"
|
requestId: []const u8, // INT-{d}"
|
||||||
@@ -275,7 +277,7 @@ const AuthChallengeResponse = enum {
|
|||||||
ProvideCredentials,
|
ProvideCredentials,
|
||||||
};
|
};
|
||||||
|
|
||||||
fn continueWithAuth(cmd: anytype) !void {
|
fn continueWithAuth(cmd: *CDP.Command) !void {
|
||||||
const bc = cmd.browser_context orelse return error.BrowserContextNotLoaded;
|
const bc = cmd.browser_context orelse return error.BrowserContextNotLoaded;
|
||||||
const params = (try cmd.params(struct {
|
const params = (try cmd.params(struct {
|
||||||
requestId: []const u8, // "INT-{d}"
|
requestId: []const u8, // "INT-{d}"
|
||||||
@@ -318,7 +320,7 @@ fn continueWithAuth(cmd: anytype) !void {
|
|||||||
return cmd.sendResult(null, .{});
|
return cmd.sendResult(null, .{});
|
||||||
}
|
}
|
||||||
|
|
||||||
fn fulfillRequest(cmd: anytype) !void {
|
fn fulfillRequest(cmd: *CDP.Command) !void {
|
||||||
const bc = cmd.browser_context orelse return error.BrowserContextNotLoaded;
|
const bc = cmd.browser_context orelse return error.BrowserContextNotLoaded;
|
||||||
|
|
||||||
const params = (try cmd.params(struct {
|
const params = (try cmd.params(struct {
|
||||||
@@ -360,7 +362,7 @@ fn fulfillRequest(cmd: anytype) !void {
|
|||||||
return cmd.sendResult(null, .{});
|
return cmd.sendResult(null, .{});
|
||||||
}
|
}
|
||||||
|
|
||||||
fn failRequest(cmd: anytype) !void {
|
fn failRequest(cmd: *CDP.Command) !void {
|
||||||
const bc = cmd.browser_context orelse return error.BrowserContextNotLoaded;
|
const bc = cmd.browser_context orelse return error.BrowserContextNotLoaded;
|
||||||
const params = (try cmd.params(struct {
|
const params = (try cmd.params(struct {
|
||||||
requestId: []const u8, // "INT-{d}"
|
requestId: []const u8, // "INT-{d}"
|
||||||
@@ -382,7 +384,7 @@ fn failRequest(cmd: anytype) !void {
|
|||||||
return cmd.sendResult(null, .{});
|
return cmd.sendResult(null, .{});
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn requestAuthRequired(bc: anytype, intercept: *const Notification.RequestAuthRequired) !void {
|
pub fn requestAuthRequired(bc: *CDP.BrowserContext, intercept: *const Notification.RequestAuthRequired) !void {
|
||||||
// detachTarget could be called, in which case, we still have a page doing
|
// detachTarget could be called, in which case, we still have a page doing
|
||||||
// things, but no session.
|
// things, but no session.
|
||||||
const session_id = bc.session_id orelse return;
|
const session_id = bc.session_id orelse return;
|
||||||
|
|||||||
@@ -17,8 +17,9 @@
|
|||||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
|
const CDP = @import("../CDP.zig");
|
||||||
|
|
||||||
pub fn processMessage(cmd: anytype) !void {
|
pub fn processMessage(cmd: *CDP.Command) !void {
|
||||||
const action = std.meta.stringToEnum(enum {
|
const action = std.meta.stringToEnum(enum {
|
||||||
dispatchKeyEvent,
|
dispatchKeyEvent,
|
||||||
dispatchMouseEvent,
|
dispatchMouseEvent,
|
||||||
@@ -33,7 +34,7 @@ pub fn processMessage(cmd: anytype) !void {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// https://chromedevtools.github.io/devtools-protocol/tot/Input/#method-dispatchKeyEvent
|
// https://chromedevtools.github.io/devtools-protocol/tot/Input/#method-dispatchKeyEvent
|
||||||
fn dispatchKeyEvent(cmd: anytype) !void {
|
fn dispatchKeyEvent(cmd: *CDP.Command) !void {
|
||||||
const params = (try cmd.params(struct {
|
const params = (try cmd.params(struct {
|
||||||
type: Type,
|
type: Type,
|
||||||
key: []const u8 = "",
|
key: []const u8 = "",
|
||||||
@@ -74,7 +75,7 @@ fn dispatchKeyEvent(cmd: anytype) !void {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// https://chromedevtools.github.io/devtools-protocol/tot/Input/#method-dispatchMouseEvent
|
// https://chromedevtools.github.io/devtools-protocol/tot/Input/#method-dispatchMouseEvent
|
||||||
fn dispatchMouseEvent(cmd: anytype) !void {
|
fn dispatchMouseEvent(cmd: *CDP.Command) !void {
|
||||||
const params = (try cmd.params(struct {
|
const params = (try cmd.params(struct {
|
||||||
x: f64,
|
x: f64,
|
||||||
y: f64,
|
y: f64,
|
||||||
@@ -104,7 +105,7 @@ fn dispatchMouseEvent(cmd: anytype) !void {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// https://chromedevtools.github.io/devtools-protocol/tot/Input/#method-insertText
|
// https://chromedevtools.github.io/devtools-protocol/tot/Input/#method-insertText
|
||||||
fn insertText(cmd: anytype) !void {
|
fn insertText(cmd: *CDP.Command) !void {
|
||||||
const params = (try cmd.params(struct {
|
const params = (try cmd.params(struct {
|
||||||
text: []const u8, // The text to insert
|
text: []const u8, // The text to insert
|
||||||
})) orelse return error.InvalidParams;
|
})) orelse return error.InvalidParams;
|
||||||
|
|||||||
@@ -17,8 +17,9 @@
|
|||||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
|
const CDP = @import("../CDP.zig");
|
||||||
|
|
||||||
pub fn processMessage(cmd: anytype) !void {
|
pub fn processMessage(cmd: *CDP.Command) !void {
|
||||||
const action = std.meta.stringToEnum(enum {
|
const action = std.meta.stringToEnum(enum {
|
||||||
enable,
|
enable,
|
||||||
disable,
|
disable,
|
||||||
|
|||||||
@@ -17,8 +17,9 @@
|
|||||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
|
const CDP = @import("../CDP.zig");
|
||||||
|
|
||||||
pub fn processMessage(cmd: anytype) !void {
|
pub fn processMessage(cmd: *CDP.Command) !void {
|
||||||
const action = std.meta.stringToEnum(enum {
|
const action = std.meta.stringToEnum(enum {
|
||||||
enable,
|
enable,
|
||||||
disable,
|
disable,
|
||||||
|
|||||||
@@ -18,14 +18,18 @@
|
|||||||
|
|
||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
const lp = @import("lightpanda");
|
const lp = @import("lightpanda");
|
||||||
|
|
||||||
|
const CDP = @import("../CDP.zig");
|
||||||
|
const Node = @import("../Node.zig");
|
||||||
|
|
||||||
|
const DOMNode = @import("../../browser/webapi/Node.zig");
|
||||||
|
|
||||||
const markdown = lp.markdown;
|
const markdown = lp.markdown;
|
||||||
const SemanticTree = lp.SemanticTree;
|
const SemanticTree = lp.SemanticTree;
|
||||||
const interactive = lp.interactive;
|
const interactive = lp.interactive;
|
||||||
const structured_data = lp.structured_data;
|
const structured_data = lp.structured_data;
|
||||||
const Node = @import("../Node.zig");
|
|
||||||
const DOMNode = @import("../../browser/webapi/Node.zig");
|
|
||||||
|
|
||||||
pub fn processMessage(cmd: anytype) !void {
|
pub fn processMessage(cmd: *CDP.Command) !void {
|
||||||
const action = std.meta.stringToEnum(enum {
|
const action = std.meta.stringToEnum(enum {
|
||||||
getMarkdown,
|
getMarkdown,
|
||||||
getSemanticTree,
|
getSemanticTree,
|
||||||
@@ -51,7 +55,7 @@ pub fn processMessage(cmd: anytype) !void {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn getSemanticTree(cmd: anytype) !void {
|
fn getSemanticTree(cmd: *CDP.Command) !void {
|
||||||
const Params = struct {
|
const Params = struct {
|
||||||
format: ?enum { text } = null,
|
format: ?enum { text } = null,
|
||||||
prune: ?bool = null,
|
prune: ?bool = null,
|
||||||
@@ -96,7 +100,7 @@ fn getSemanticTree(cmd: anytype) !void {
|
|||||||
}, .{});
|
}, .{});
|
||||||
}
|
}
|
||||||
|
|
||||||
fn getMarkdown(cmd: anytype) !void {
|
fn getMarkdown(cmd: *CDP.Command) !void {
|
||||||
const Params = struct {
|
const Params = struct {
|
||||||
nodeId: ?Node.Id = null,
|
nodeId: ?Node.Id = null,
|
||||||
};
|
};
|
||||||
@@ -119,7 +123,7 @@ fn getMarkdown(cmd: anytype) !void {
|
|||||||
}, .{});
|
}, .{});
|
||||||
}
|
}
|
||||||
|
|
||||||
fn getInteractiveElements(cmd: anytype) !void {
|
fn getInteractiveElements(cmd: *CDP.Command) !void {
|
||||||
const Params = struct {
|
const Params = struct {
|
||||||
nodeId: ?Node.Id = null,
|
nodeId: ?Node.Id = null,
|
||||||
};
|
};
|
||||||
@@ -141,7 +145,7 @@ fn getInteractiveElements(cmd: anytype) !void {
|
|||||||
}, .{});
|
}, .{});
|
||||||
}
|
}
|
||||||
|
|
||||||
fn getStructuredData(cmd: anytype) !void {
|
fn getStructuredData(cmd: *CDP.Command) !void {
|
||||||
const bc = cmd.browser_context orelse return error.NoBrowserContext;
|
const bc = cmd.browser_context orelse return error.NoBrowserContext;
|
||||||
const page = bc.session.currentPage() orelse return error.PageNotLoaded;
|
const page = bc.session.currentPage() orelse return error.PageNotLoaded;
|
||||||
|
|
||||||
@@ -156,7 +160,7 @@ fn getStructuredData(cmd: anytype) !void {
|
|||||||
}, .{});
|
}, .{});
|
||||||
}
|
}
|
||||||
|
|
||||||
fn detectForms(cmd: anytype) !void {
|
fn detectForms(cmd: *CDP.Command) !void {
|
||||||
const bc = cmd.browser_context orelse return error.NoBrowserContext;
|
const bc = cmd.browser_context orelse return error.NoBrowserContext;
|
||||||
const page = bc.session.currentPage() orelse return error.PageNotLoaded;
|
const page = bc.session.currentPage() orelse return error.PageNotLoaded;
|
||||||
|
|
||||||
@@ -173,7 +177,7 @@ fn detectForms(cmd: anytype) !void {
|
|||||||
}, .{});
|
}, .{});
|
||||||
}
|
}
|
||||||
|
|
||||||
fn clickNode(cmd: anytype) !void {
|
fn clickNode(cmd: *CDP.Command) !void {
|
||||||
const Params = struct {
|
const Params = struct {
|
||||||
nodeId: ?Node.Id = null,
|
nodeId: ?Node.Id = null,
|
||||||
backendNodeId: ?Node.Id = null,
|
backendNodeId: ?Node.Id = null,
|
||||||
@@ -194,7 +198,7 @@ fn clickNode(cmd: anytype) !void {
|
|||||||
return cmd.sendResult(.{}, .{});
|
return cmd.sendResult(.{}, .{});
|
||||||
}
|
}
|
||||||
|
|
||||||
fn fillNode(cmd: anytype) !void {
|
fn fillNode(cmd: *CDP.Command) !void {
|
||||||
const Params = struct {
|
const Params = struct {
|
||||||
nodeId: ?Node.Id = null,
|
nodeId: ?Node.Id = null,
|
||||||
backendNodeId: ?Node.Id = null,
|
backendNodeId: ?Node.Id = null,
|
||||||
@@ -216,7 +220,7 @@ fn fillNode(cmd: anytype) !void {
|
|||||||
return cmd.sendResult(.{}, .{});
|
return cmd.sendResult(.{}, .{});
|
||||||
}
|
}
|
||||||
|
|
||||||
fn scrollNode(cmd: anytype) !void {
|
fn scrollNode(cmd: *CDP.Command) !void {
|
||||||
const Params = struct {
|
const Params = struct {
|
||||||
nodeId: ?Node.Id = null,
|
nodeId: ?Node.Id = null,
|
||||||
backendNodeId: ?Node.Id = null,
|
backendNodeId: ?Node.Id = null,
|
||||||
@@ -244,7 +248,7 @@ fn scrollNode(cmd: anytype) !void {
|
|||||||
return cmd.sendResult(.{}, .{});
|
return cmd.sendResult(.{}, .{});
|
||||||
}
|
}
|
||||||
|
|
||||||
fn waitForSelector(cmd: anytype) !void {
|
fn waitForSelector(cmd: *CDP.Command) !void {
|
||||||
const Params = struct {
|
const Params = struct {
|
||||||
selector: []const u8,
|
selector: []const u8,
|
||||||
timeout: ?u32 = null,
|
timeout: ?u32 = null,
|
||||||
|
|||||||
@@ -18,18 +18,21 @@
|
|||||||
|
|
||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
const lp = @import("lightpanda");
|
const lp = @import("lightpanda");
|
||||||
const Allocator = std.mem.Allocator;
|
|
||||||
const log = @import("../../log.zig");
|
const log = @import("../../log.zig");
|
||||||
|
|
||||||
const CdpStorage = @import("storage.zig");
|
|
||||||
|
|
||||||
const id = @import("../id.zig");
|
const id = @import("../id.zig");
|
||||||
|
const CDP = @import("../CDP.zig");
|
||||||
|
|
||||||
const URL = @import("../../browser/URL.zig");
|
const URL = @import("../../browser/URL.zig");
|
||||||
const Transfer = @import("../../browser/HttpClient.zig").Transfer;
|
const Transfer = @import("../../browser/HttpClient.zig").Transfer;
|
||||||
const Notification = @import("../../Notification.zig");
|
const Notification = @import("../../Notification.zig");
|
||||||
const Mime = @import("../../browser/Mime.zig");
|
const Mime = @import("../../browser/Mime.zig");
|
||||||
|
|
||||||
pub fn processMessage(cmd: anytype) !void {
|
const CdpStorage = @import("storage.zig");
|
||||||
|
const Allocator = std.mem.Allocator;
|
||||||
|
|
||||||
|
pub fn processMessage(cmd: *CDP.Command) !void {
|
||||||
const action = std.meta.stringToEnum(enum {
|
const action = std.meta.stringToEnum(enum {
|
||||||
enable,
|
enable,
|
||||||
disable,
|
disable,
|
||||||
@@ -59,19 +62,19 @@ pub fn processMessage(cmd: anytype) !void {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn enable(cmd: anytype) !void {
|
fn enable(cmd: *CDP.Command) !void {
|
||||||
const bc = cmd.browser_context orelse return error.BrowserContextNotLoaded;
|
const bc = cmd.browser_context orelse return error.BrowserContextNotLoaded;
|
||||||
try bc.networkEnable();
|
try bc.networkEnable();
|
||||||
return cmd.sendResult(null, .{});
|
return cmd.sendResult(null, .{});
|
||||||
}
|
}
|
||||||
|
|
||||||
fn disable(cmd: anytype) !void {
|
fn disable(cmd: *CDP.Command) !void {
|
||||||
const bc = cmd.browser_context orelse return error.BrowserContextNotLoaded;
|
const bc = cmd.browser_context orelse return error.BrowserContextNotLoaded;
|
||||||
bc.networkDisable();
|
bc.networkDisable();
|
||||||
return cmd.sendResult(null, .{});
|
return cmd.sendResult(null, .{});
|
||||||
}
|
}
|
||||||
|
|
||||||
fn setExtraHTTPHeaders(cmd: anytype) !void {
|
fn setExtraHTTPHeaders(cmd: *CDP.Command) !void {
|
||||||
const params = (try cmd.params(struct {
|
const params = (try cmd.params(struct {
|
||||||
headers: std.json.ArrayHashMap([]const u8),
|
headers: std.json.ArrayHashMap([]const u8),
|
||||||
})) orelse return error.InvalidParams;
|
})) orelse return error.InvalidParams;
|
||||||
@@ -110,7 +113,7 @@ fn cookieMatches(cookie: *const Cookie, name: []const u8, domain: ?[]const u8, p
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn deleteCookies(cmd: anytype) !void {
|
fn deleteCookies(cmd: *CDP.Command) !void {
|
||||||
const params = (try cmd.params(struct {
|
const params = (try cmd.params(struct {
|
||||||
name: []const u8,
|
name: []const u8,
|
||||||
url: ?[:0]const u8 = null,
|
url: ?[:0]const u8 = null,
|
||||||
@@ -144,14 +147,14 @@ fn deleteCookies(cmd: anytype) !void {
|
|||||||
return cmd.sendResult(null, .{});
|
return cmd.sendResult(null, .{});
|
||||||
}
|
}
|
||||||
|
|
||||||
fn clearBrowserCookies(cmd: anytype) !void {
|
fn clearBrowserCookies(cmd: *CDP.Command) !void {
|
||||||
if (try cmd.params(struct {}) != null) return error.InvalidParams;
|
if (try cmd.params(struct {}) != null) return error.InvalidParams;
|
||||||
const bc = cmd.browser_context orelse return error.BrowserContextNotLoaded;
|
const bc = cmd.browser_context orelse return error.BrowserContextNotLoaded;
|
||||||
bc.session.cookie_jar.clearRetainingCapacity();
|
bc.session.cookie_jar.clearRetainingCapacity();
|
||||||
return cmd.sendResult(null, .{});
|
return cmd.sendResult(null, .{});
|
||||||
}
|
}
|
||||||
|
|
||||||
fn setCookie(cmd: anytype) !void {
|
fn setCookie(cmd: *CDP.Command) !void {
|
||||||
const params = (try cmd.params(
|
const params = (try cmd.params(
|
||||||
CdpStorage.CdpCookie,
|
CdpStorage.CdpCookie,
|
||||||
)) orelse return error.InvalidParams;
|
)) orelse return error.InvalidParams;
|
||||||
@@ -162,7 +165,7 @@ fn setCookie(cmd: anytype) !void {
|
|||||||
try cmd.sendResult(.{ .success = true }, .{});
|
try cmd.sendResult(.{ .success = true }, .{});
|
||||||
}
|
}
|
||||||
|
|
||||||
fn setCookies(cmd: anytype) !void {
|
fn setCookies(cmd: *CDP.Command) !void {
|
||||||
const params = (try cmd.params(struct {
|
const params = (try cmd.params(struct {
|
||||||
cookies: []const CdpStorage.CdpCookie,
|
cookies: []const CdpStorage.CdpCookie,
|
||||||
})) orelse return error.InvalidParams;
|
})) orelse return error.InvalidParams;
|
||||||
@@ -178,7 +181,7 @@ fn setCookies(cmd: anytype) !void {
|
|||||||
const GetCookiesParam = struct {
|
const GetCookiesParam = struct {
|
||||||
urls: ?[]const [:0]const u8 = null,
|
urls: ?[]const [:0]const u8 = null,
|
||||||
};
|
};
|
||||||
fn getCookies(cmd: anytype) !void {
|
fn getCookies(cmd: *CDP.Command) !void {
|
||||||
const bc = cmd.browser_context orelse return error.BrowserContextNotLoaded;
|
const bc = cmd.browser_context orelse return error.BrowserContextNotLoaded;
|
||||||
const params = (try cmd.params(GetCookiesParam)) orelse GetCookiesParam{};
|
const params = (try cmd.params(GetCookiesParam)) orelse GetCookiesParam{};
|
||||||
|
|
||||||
@@ -201,7 +204,7 @@ fn getCookies(cmd: anytype) !void {
|
|||||||
try cmd.sendResult(.{ .cookies = writer }, .{});
|
try cmd.sendResult(.{ .cookies = writer }, .{});
|
||||||
}
|
}
|
||||||
|
|
||||||
fn getResponseBody(cmd: anytype) !void {
|
fn getResponseBody(cmd: *CDP.Command) !void {
|
||||||
const params = (try cmd.params(struct {
|
const params = (try cmd.params(struct {
|
||||||
requestId: []const u8, // "REQ-{d}"
|
requestId: []const u8, // "REQ-{d}"
|
||||||
})) orelse return error.InvalidParams;
|
})) orelse return error.InvalidParams;
|
||||||
@@ -227,7 +230,7 @@ fn getResponseBody(cmd: anytype) !void {
|
|||||||
}, .{});
|
}, .{});
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn httpRequestFail(bc: anytype, msg: *const Notification.RequestFail) !void {
|
pub fn httpRequestFail(bc: *CDP.BrowserContext, msg: *const Notification.RequestFail) !void {
|
||||||
// It's possible that the request failed because we aborted when the client
|
// It's possible that the request failed because we aborted when the client
|
||||||
// sent Target.closeTarget. In that case, bc.session_id will be cleared
|
// sent Target.closeTarget. In that case, bc.session_id will be cleared
|
||||||
// already, and we can skip sending these messages to the client.
|
// already, and we can skip sending these messages to the client.
|
||||||
@@ -247,7 +250,7 @@ pub fn httpRequestFail(bc: anytype, msg: *const Notification.RequestFail) !void
|
|||||||
}, .{ .session_id = session_id });
|
}, .{ .session_id = session_id });
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn httpRequestStart(bc: anytype, msg: *const Notification.RequestStart) !void {
|
pub fn httpRequestStart(bc: *CDP.BrowserContext, msg: *const Notification.RequestStart) !void {
|
||||||
// detachTarget could be called, in which case, we still have a page doing
|
// detachTarget could be called, in which case, we still have a page doing
|
||||||
// things, but no session.
|
// things, but no session.
|
||||||
const session_id = bc.session_id orelse return;
|
const session_id = bc.session_id orelse return;
|
||||||
@@ -276,7 +279,7 @@ pub fn httpRequestStart(bc: anytype, msg: *const Notification.RequestStart) !voi
|
|||||||
}, .{ .session_id = session_id });
|
}, .{ .session_id = session_id });
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn httpResponseHeaderDone(arena: Allocator, bc: anytype, msg: *const Notification.ResponseHeaderDone) !void {
|
pub fn httpResponseHeaderDone(arena: Allocator, bc: *CDP.BrowserContext, msg: *const Notification.ResponseHeaderDone) !void {
|
||||||
// detachTarget could be called, in which case, we still have a page doing
|
// detachTarget could be called, in which case, we still have a page doing
|
||||||
// things, but no session.
|
// things, but no session.
|
||||||
const session_id = bc.session_id orelse return;
|
const session_id = bc.session_id orelse return;
|
||||||
@@ -293,7 +296,7 @@ pub fn httpResponseHeaderDone(arena: Allocator, bc: anytype, msg: *const Notific
|
|||||||
}, .{ .session_id = session_id });
|
}, .{ .session_id = session_id });
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn httpRequestDone(bc: anytype, msg: *const Notification.RequestDone) !void {
|
pub fn httpRequestDone(bc: *CDP.BrowserContext, msg: *const Notification.RequestDone) !void {
|
||||||
// detachTarget could be called, in which case, we still have a page doing
|
// detachTarget could be called, in which case, we still have a page doing
|
||||||
// things, but no session.
|
// things, but no session.
|
||||||
const session_id = bc.session_id orelse return;
|
const session_id = bc.session_id orelse return;
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
// Copyright (C) 2023-2025 Lightpanda (Selecy SAS)
|
// Copyright (C) 2023-2025 Lightpanda (Selecy SAS)
|
||||||
|
|
||||||
//
|
//
|
||||||
// Francis Bouvier <francis@lightpanda.io>
|
// Francis Bouvier <francis@lightpanda.io>
|
||||||
// Pierre Tachoire <pierre@lightpanda.io>
|
// Pierre Tachoire <pierre@lightpanda.io>
|
||||||
@@ -22,6 +23,8 @@ const lp = @import("lightpanda");
|
|||||||
const screenshot_png = @embedFile("screenshot.png");
|
const screenshot_png = @embedFile("screenshot.png");
|
||||||
|
|
||||||
const id = @import("../id.zig");
|
const id = @import("../id.zig");
|
||||||
|
const CDP = @import("../CDP.zig");
|
||||||
|
|
||||||
const log = @import("../../log.zig");
|
const log = @import("../../log.zig");
|
||||||
const js = @import("../../browser/js/js.zig");
|
const js = @import("../../browser/js/js.zig");
|
||||||
const URL = @import("../../browser/URL.zig");
|
const URL = @import("../../browser/URL.zig");
|
||||||
@@ -31,7 +34,7 @@ const Notification = @import("../../Notification.zig");
|
|||||||
|
|
||||||
const Allocator = std.mem.Allocator;
|
const Allocator = std.mem.Allocator;
|
||||||
|
|
||||||
pub fn processMessage(cmd: anytype) !void {
|
pub fn processMessage(cmd: *CDP.Command) !void {
|
||||||
const action = std.meta.stringToEnum(enum {
|
const action = std.meta.stringToEnum(enum {
|
||||||
enable,
|
enable,
|
||||||
getFrameTree,
|
getFrameTree,
|
||||||
@@ -78,7 +81,7 @@ const Frame = struct {
|
|||||||
gatedAPIFeatures: [][]const u8 = &[0][]const u8{},
|
gatedAPIFeatures: [][]const u8 = &[0][]const u8{},
|
||||||
};
|
};
|
||||||
|
|
||||||
fn getFrameTree(cmd: anytype) !void {
|
fn getFrameTree(cmd: *CDP.Command) !void {
|
||||||
// Stagehand parses the response and error if we don't return a
|
// Stagehand parses the response and error if we don't return a
|
||||||
// correct one for this call when browser context or target id are missing.
|
// correct one for this call when browser context or target id are missing.
|
||||||
const startup = .{
|
const startup = .{
|
||||||
@@ -108,7 +111,7 @@ fn getFrameTree(cmd: anytype) !void {
|
|||||||
}, .{});
|
}, .{});
|
||||||
}
|
}
|
||||||
|
|
||||||
fn setLifecycleEventsEnabled(cmd: anytype) !void {
|
fn setLifecycleEventsEnabled(cmd: *CDP.Command) !void {
|
||||||
const params = (try cmd.params(struct {
|
const params = (try cmd.params(struct {
|
||||||
enabled: bool,
|
enabled: bool,
|
||||||
})) orelse return error.InvalidParams;
|
})) orelse return error.InvalidParams;
|
||||||
@@ -149,7 +152,7 @@ fn setLifecycleEventsEnabled(cmd: anytype) !void {
|
|||||||
return cmd.sendResult(null, .{});
|
return cmd.sendResult(null, .{});
|
||||||
}
|
}
|
||||||
|
|
||||||
fn addScriptToEvaluateOnNewDocument(cmd: anytype) !void {
|
fn addScriptToEvaluateOnNewDocument(cmd: *CDP.Command) !void {
|
||||||
const params = (try cmd.params(struct {
|
const params = (try cmd.params(struct {
|
||||||
source: []const u8,
|
source: []const u8,
|
||||||
worldName: ?[]const u8 = null,
|
worldName: ?[]const u8 = null,
|
||||||
@@ -179,7 +182,7 @@ fn addScriptToEvaluateOnNewDocument(cmd: anytype) !void {
|
|||||||
}, .{});
|
}, .{});
|
||||||
}
|
}
|
||||||
|
|
||||||
fn removeScriptToEvaluateOnNewDocument(cmd: anytype) !void {
|
fn removeScriptToEvaluateOnNewDocument(cmd: *CDP.Command) !void {
|
||||||
const params = (try cmd.params(struct {
|
const params = (try cmd.params(struct {
|
||||||
identifier: []const u8,
|
identifier: []const u8,
|
||||||
})) orelse return error.InvalidParams;
|
})) orelse return error.InvalidParams;
|
||||||
@@ -198,7 +201,7 @@ fn removeScriptToEvaluateOnNewDocument(cmd: anytype) !void {
|
|||||||
return cmd.sendResult(null, .{});
|
return cmd.sendResult(null, .{});
|
||||||
}
|
}
|
||||||
|
|
||||||
fn close(cmd: anytype) !void {
|
fn close(cmd: *CDP.Command) !void {
|
||||||
const bc = cmd.browser_context orelse return error.BrowserContextNotLoaded;
|
const bc = cmd.browser_context orelse return error.BrowserContextNotLoaded;
|
||||||
|
|
||||||
const target_id = bc.target_id orelse return error.TargetNotLoaded;
|
const target_id = bc.target_id orelse return error.TargetNotLoaded;
|
||||||
@@ -235,7 +238,7 @@ fn close(cmd: anytype) !void {
|
|||||||
bc.target_id = null;
|
bc.target_id = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn createIsolatedWorld(cmd: anytype) !void {
|
fn createIsolatedWorld(cmd: *CDP.Command) !void {
|
||||||
const params = (try cmd.params(struct {
|
const params = (try cmd.params(struct {
|
||||||
frameId: []const u8,
|
frameId: []const u8,
|
||||||
worldName: []const u8,
|
worldName: []const u8,
|
||||||
@@ -255,7 +258,7 @@ fn createIsolatedWorld(cmd: anytype) !void {
|
|||||||
return cmd.sendResult(.{ .executionContextId = js_context.id }, .{});
|
return cmd.sendResult(.{ .executionContextId = js_context.id }, .{});
|
||||||
}
|
}
|
||||||
|
|
||||||
fn navigate(cmd: anytype) !void {
|
fn navigate(cmd: *CDP.Command) !void {
|
||||||
const params = (try cmd.params(struct {
|
const params = (try cmd.params(struct {
|
||||||
url: [:0]const u8,
|
url: [:0]const u8,
|
||||||
// referrer: ?[]const u8 = null,
|
// referrer: ?[]const u8 = null,
|
||||||
@@ -289,7 +292,7 @@ fn navigate(cmd: anytype) !void {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
fn doReload(cmd: anytype) !void {
|
fn doReload(cmd: *CDP.Command) !void {
|
||||||
const params = try cmd.params(struct {
|
const params = try cmd.params(struct {
|
||||||
ignoreCache: ?bool = null,
|
ignoreCache: ?bool = null,
|
||||||
scriptToEvaluateOnLoad: ?[]const u8 = null,
|
scriptToEvaluateOnLoad: ?[]const u8 = null,
|
||||||
@@ -319,7 +322,7 @@ fn doReload(cmd: anytype) !void {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn pageNavigate(bc: anytype, event: *const Notification.PageNavigate) !void {
|
pub fn pageNavigate(bc: *CDP.BrowserContext, event: *const Notification.PageNavigate) !void {
|
||||||
// detachTarget could be called, in which case, we still have a page doing
|
// detachTarget could be called, in which case, we still have a page doing
|
||||||
// things, but no session.
|
// things, but no session.
|
||||||
const session_id = bc.session_id orelse return;
|
const session_id = bc.session_id orelse return;
|
||||||
@@ -371,7 +374,7 @@ pub fn pageNavigate(bc: anytype, event: *const Notification.PageNavigate) !void
|
|||||||
}, .{ .session_id = session_id });
|
}, .{ .session_id = session_id });
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn pageRemove(bc: anytype) !void {
|
pub fn pageRemove(bc: *CDP.BrowserContext) !void {
|
||||||
// Clear all remote object mappings to prevent stale objectIds from being used
|
// Clear all remote object mappings to prevent stale objectIds from being used
|
||||||
// after the context is destroy
|
// after the context is destroy
|
||||||
bc.inspector_session.inspector.resetContextGroup();
|
bc.inspector_session.inspector.resetContextGroup();
|
||||||
@@ -382,7 +385,7 @@ pub fn pageRemove(bc: anytype) !void {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn pageCreated(bc: anytype, page: *Page) !void {
|
pub fn pageCreated(bc: *CDP.BrowserContext, page: *Page) !void {
|
||||||
_ = bc.cdp.page_arena.reset(.{ .retain_with_limit = 1024 * 512 });
|
_ = bc.cdp.page_arena.reset(.{ .retain_with_limit = 1024 * 512 });
|
||||||
|
|
||||||
for (bc.isolated_worlds.items) |isolated_world| {
|
for (bc.isolated_worlds.items) |isolated_world| {
|
||||||
@@ -394,7 +397,7 @@ pub fn pageCreated(bc: anytype, page: *Page) !void {
|
|||||||
bc.captured_responses = .empty;
|
bc.captured_responses = .empty;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn pageFrameCreated(bc: anytype, event: *const Notification.PageFrameCreated) !void {
|
pub fn pageFrameCreated(bc: *CDP.BrowserContext, event: *const Notification.PageFrameCreated) !void {
|
||||||
const session_id = bc.session_id orelse return;
|
const session_id = bc.session_id orelse return;
|
||||||
|
|
||||||
const cdp = bc.cdp;
|
const cdp = bc.cdp;
|
||||||
@@ -415,7 +418,7 @@ pub fn pageFrameCreated(bc: anytype, event: *const Notification.PageFrameCreated
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn pageNavigated(arena: Allocator, bc: anytype, event: *const Notification.PageNavigated) !void {
|
pub fn pageNavigated(arena: Allocator, bc: *CDP.BrowserContext, event: *const Notification.PageNavigated) !void {
|
||||||
// detachTarget could be called, in which case, we still have a page doing
|
// detachTarget could be called, in which case, we still have a page doing
|
||||||
// things, but no session.
|
// things, but no session.
|
||||||
const session_id = bc.session_id orelse return;
|
const session_id = bc.session_id orelse return;
|
||||||
@@ -597,15 +600,15 @@ pub fn pageNavigated(arena: Allocator, bc: anytype, event: *const Notification.P
|
|||||||
}, .{ .session_id = session_id });
|
}, .{ .session_id = session_id });
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn pageNetworkIdle(bc: anytype, event: *const Notification.PageNetworkIdle) !void {
|
pub fn pageNetworkIdle(bc: *CDP.BrowserContext, event: *const Notification.PageNetworkIdle) !void {
|
||||||
return sendPageLifecycle(bc, "networkIdle", event.timestamp, &id.toFrameId(event.frame_id), &id.toLoaderId(event.req_id));
|
return sendPageLifecycle(bc, "networkIdle", event.timestamp, &id.toFrameId(event.frame_id), &id.toLoaderId(event.req_id));
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn pageNetworkAlmostIdle(bc: anytype, event: *const Notification.PageNetworkAlmostIdle) !void {
|
pub fn pageNetworkAlmostIdle(bc: *CDP.BrowserContext, event: *const Notification.PageNetworkAlmostIdle) !void {
|
||||||
return sendPageLifecycle(bc, "networkAlmostIdle", event.timestamp, &id.toFrameId(event.frame_id), &id.toLoaderId(event.req_id));
|
return sendPageLifecycle(bc, "networkAlmostIdle", event.timestamp, &id.toFrameId(event.frame_id), &id.toLoaderId(event.req_id));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn sendPageLifecycle(bc: anytype, name: []const u8, timestamp: u64, frame_id: []const u8, loader_id: []const u8) !void {
|
fn sendPageLifecycle(bc: *CDP.BrowserContext, name: []const u8, timestamp: u64, frame_id: []const u8, loader_id: []const u8) !void {
|
||||||
// detachTarget could be called, in which case, we still have a page doing
|
// detachTarget could be called, in which case, we still have a page doing
|
||||||
// things, but no session.
|
// things, but no session.
|
||||||
const session_id = bc.session_id orelse return;
|
const session_id = bc.session_id orelse return;
|
||||||
@@ -640,7 +643,7 @@ fn base64Encode(comptime input: []const u8) [std.base64.standard.Encoder.calcSiz
|
|||||||
return buf;
|
return buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn captureScreenshot(cmd: anytype) !void {
|
fn captureScreenshot(cmd: *CDP.Command) !void {
|
||||||
const Params = struct {
|
const Params = struct {
|
||||||
format: ?[]const u8 = "png",
|
format: ?[]const u8 = "png",
|
||||||
quality: ?u8 = null,
|
quality: ?u8 = null,
|
||||||
@@ -676,7 +679,7 @@ fn captureScreenshot(cmd: anytype) !void {
|
|||||||
}, .{});
|
}, .{});
|
||||||
}
|
}
|
||||||
|
|
||||||
fn getLayoutMetrics(cmd: anytype) !void {
|
fn getLayoutMetrics(cmd: *CDP.Command) !void {
|
||||||
const width = 1920;
|
const width = 1920;
|
||||||
const height = 1080;
|
const height = 1080;
|
||||||
|
|
||||||
|
|||||||
@@ -17,8 +17,9 @@
|
|||||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
|
const CDP = @import("../CDP.zig");
|
||||||
|
|
||||||
pub fn processMessage(cmd: anytype) !void {
|
pub fn processMessage(cmd: *CDP.Command) !void {
|
||||||
const action = std.meta.stringToEnum(enum {
|
const action = std.meta.stringToEnum(enum {
|
||||||
enable,
|
enable,
|
||||||
disable,
|
disable,
|
||||||
|
|||||||
@@ -19,7 +19,9 @@
|
|||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
const builtin = @import("builtin");
|
const builtin = @import("builtin");
|
||||||
|
|
||||||
pub fn processMessage(cmd: anytype) !void {
|
const CDP = @import("../CDP.zig");
|
||||||
|
|
||||||
|
pub fn processMessage(cmd: *CDP.Command) !void {
|
||||||
const action = std.meta.stringToEnum(enum {
|
const action = std.meta.stringToEnum(enum {
|
||||||
enable,
|
enable,
|
||||||
runIfWaitingForDebugger,
|
runIfWaitingForDebugger,
|
||||||
@@ -36,7 +38,7 @@ pub fn processMessage(cmd: anytype) !void {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn sendInspector(cmd: anytype, action: anytype) !void {
|
fn sendInspector(cmd: *CDP.Command, action: anytype) !void {
|
||||||
// save script in file at debug mode
|
// save script in file at debug mode
|
||||||
if (builtin.mode == .Debug) {
|
if (builtin.mode == .Debug) {
|
||||||
try logInspector(cmd, action);
|
try logInspector(cmd, action);
|
||||||
@@ -48,7 +50,7 @@ fn sendInspector(cmd: anytype, action: anytype) !void {
|
|||||||
bc.callInspector(cmd.input.json);
|
bc.callInspector(cmd.input.json);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn logInspector(cmd: anytype, action: anytype) !void {
|
fn logInspector(cmd: *CDP.Command, action: anytype) !void {
|
||||||
const script = switch (action) {
|
const script = switch (action) {
|
||||||
.evaluate => blk: {
|
.evaluate => blk: {
|
||||||
const params = (try cmd.params(struct {
|
const params = (try cmd.params(struct {
|
||||||
|
|||||||
@@ -17,8 +17,9 @@
|
|||||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
|
const CDP = @import("../CDP.zig");
|
||||||
|
|
||||||
pub fn processMessage(cmd: anytype) !void {
|
pub fn processMessage(cmd: *CDP.Command) !void {
|
||||||
const action = std.meta.stringToEnum(enum {
|
const action = std.meta.stringToEnum(enum {
|
||||||
enable,
|
enable,
|
||||||
disable,
|
disable,
|
||||||
@@ -32,7 +33,7 @@ pub fn processMessage(cmd: anytype) !void {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn setIgnoreCertificateErrors(cmd: anytype) !void {
|
fn setIgnoreCertificateErrors(cmd: *CDP.Command) !void {
|
||||||
const params = (try cmd.params(struct {
|
const params = (try cmd.params(struct {
|
||||||
ignore: bool,
|
ignore: bool,
|
||||||
})) orelse return error.InvalidParams;
|
})) orelse return error.InvalidParams;
|
||||||
|
|||||||
@@ -18,13 +18,16 @@
|
|||||||
|
|
||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
|
|
||||||
|
const CDP = @import("../CDP.zig");
|
||||||
|
|
||||||
const log = @import("../../log.zig");
|
const log = @import("../../log.zig");
|
||||||
const URL = @import("../../browser/URL.zig");
|
const URL = @import("../../browser/URL.zig");
|
||||||
const Cookie = @import("../../browser/webapi/storage/storage.zig").Cookie;
|
const Cookie = @import("../../browser/webapi/storage/storage.zig").Cookie;
|
||||||
|
|
||||||
const CookieJar = Cookie.Jar;
|
const CookieJar = Cookie.Jar;
|
||||||
pub const PreparedUri = Cookie.PreparedUri;
|
pub const PreparedUri = Cookie.PreparedUri;
|
||||||
|
|
||||||
pub fn processMessage(cmd: anytype) !void {
|
pub fn processMessage(cmd: *CDP.Command) !void {
|
||||||
const action = std.meta.stringToEnum(enum {
|
const action = std.meta.stringToEnum(enum {
|
||||||
clearCookies,
|
clearCookies,
|
||||||
setCookies,
|
setCookies,
|
||||||
@@ -40,7 +43,7 @@ pub fn processMessage(cmd: anytype) !void {
|
|||||||
|
|
||||||
const BrowserContextParam = struct { browserContextId: ?[]const u8 = null };
|
const BrowserContextParam = struct { browserContextId: ?[]const u8 = null };
|
||||||
|
|
||||||
fn clearCookies(cmd: anytype) !void {
|
fn clearCookies(cmd: *CDP.Command) !void {
|
||||||
const bc = cmd.browser_context orelse return error.BrowserContextNotLoaded;
|
const bc = cmd.browser_context orelse return error.BrowserContextNotLoaded;
|
||||||
const params = (try cmd.params(BrowserContextParam)) orelse BrowserContextParam{};
|
const params = (try cmd.params(BrowserContextParam)) orelse BrowserContextParam{};
|
||||||
|
|
||||||
@@ -55,7 +58,7 @@ fn clearCookies(cmd: anytype) !void {
|
|||||||
return cmd.sendResult(null, .{});
|
return cmd.sendResult(null, .{});
|
||||||
}
|
}
|
||||||
|
|
||||||
fn getCookies(cmd: anytype) !void {
|
fn getCookies(cmd: *CDP.Command) !void {
|
||||||
const bc = cmd.browser_context orelse return error.BrowserContextNotLoaded;
|
const bc = cmd.browser_context orelse return error.BrowserContextNotLoaded;
|
||||||
const params = (try cmd.params(BrowserContextParam)) orelse BrowserContextParam{};
|
const params = (try cmd.params(BrowserContextParam)) orelse BrowserContextParam{};
|
||||||
|
|
||||||
@@ -69,7 +72,7 @@ fn getCookies(cmd: anytype) !void {
|
|||||||
try cmd.sendResult(.{ .cookies = writer }, .{});
|
try cmd.sendResult(.{ .cookies = writer }, .{});
|
||||||
}
|
}
|
||||||
|
|
||||||
fn setCookies(cmd: anytype) !void {
|
fn setCookies(cmd: *CDP.Command) !void {
|
||||||
const bc = cmd.browser_context orelse return error.BrowserContextNotLoaded;
|
const bc = cmd.browser_context orelse return error.BrowserContextNotLoaded;
|
||||||
const params = (try cmd.params(struct {
|
const params = (try cmd.params(struct {
|
||||||
cookies: []const CdpCookie,
|
cookies: []const CdpCookie,
|
||||||
|
|||||||
@@ -20,11 +20,13 @@ const std = @import("std");
|
|||||||
const lp = @import("lightpanda");
|
const lp = @import("lightpanda");
|
||||||
|
|
||||||
const id = @import("../id.zig");
|
const id = @import("../id.zig");
|
||||||
|
const CDP = @import("../CDP.zig");
|
||||||
|
|
||||||
const log = @import("../../log.zig");
|
const log = @import("../../log.zig");
|
||||||
const URL = @import("../../browser/URL.zig");
|
const URL = @import("../../browser/URL.zig");
|
||||||
const js = @import("../../browser/js/js.zig");
|
const js = @import("../../browser/js/js.zig");
|
||||||
|
|
||||||
pub fn processMessage(cmd: anytype) !void {
|
pub fn processMessage(cmd: *CDP.Command) !void {
|
||||||
const action = std.meta.stringToEnum(enum {
|
const action = std.meta.stringToEnum(enum {
|
||||||
getTargets,
|
getTargets,
|
||||||
attachToTarget,
|
attachToTarget,
|
||||||
@@ -60,7 +62,7 @@ pub fn processMessage(cmd: anytype) !void {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn getTargets(cmd: anytype) !void {
|
fn getTargets(cmd: *CDP.Command) !void {
|
||||||
// If no context available, return an empty array.
|
// If no context available, return an empty array.
|
||||||
const bc = cmd.browser_context orelse {
|
const bc = cmd.browser_context orelse {
|
||||||
return cmd.sendResult(.{
|
return cmd.sendResult(.{
|
||||||
@@ -86,7 +88,7 @@ fn getTargets(cmd: anytype) !void {
|
|||||||
}, .{ .include_session_id = false });
|
}, .{ .include_session_id = false });
|
||||||
}
|
}
|
||||||
|
|
||||||
fn getBrowserContexts(cmd: anytype) !void {
|
fn getBrowserContexts(cmd: *CDP.Command) !void {
|
||||||
var browser_context_ids: []const []const u8 = undefined;
|
var browser_context_ids: []const []const u8 = undefined;
|
||||||
if (cmd.browser_context) |bc| {
|
if (cmd.browser_context) |bc| {
|
||||||
browser_context_ids = &.{bc.id};
|
browser_context_ids = &.{bc.id};
|
||||||
@@ -99,7 +101,7 @@ fn getBrowserContexts(cmd: anytype) !void {
|
|||||||
}, .{ .include_session_id = false });
|
}, .{ .include_session_id = false });
|
||||||
}
|
}
|
||||||
|
|
||||||
fn createBrowserContext(cmd: anytype) !void {
|
fn createBrowserContext(cmd: *CDP.Command) !void {
|
||||||
const params = try cmd.params(struct {
|
const params = try cmd.params(struct {
|
||||||
disposeOnDetach: bool = false,
|
disposeOnDetach: bool = false,
|
||||||
proxyServer: ?[:0]const u8 = null,
|
proxyServer: ?[:0]const u8 = null,
|
||||||
@@ -130,7 +132,7 @@ fn createBrowserContext(cmd: anytype) !void {
|
|||||||
}, .{});
|
}, .{});
|
||||||
}
|
}
|
||||||
|
|
||||||
fn disposeBrowserContext(cmd: anytype) !void {
|
fn disposeBrowserContext(cmd: *CDP.Command) !void {
|
||||||
const params = (try cmd.params(struct {
|
const params = (try cmd.params(struct {
|
||||||
browserContextId: []const u8,
|
browserContextId: []const u8,
|
||||||
})) orelse return error.InvalidParams;
|
})) orelse return error.InvalidParams;
|
||||||
@@ -141,7 +143,7 @@ fn disposeBrowserContext(cmd: anytype) !void {
|
|||||||
try cmd.sendResult(null, .{});
|
try cmd.sendResult(null, .{});
|
||||||
}
|
}
|
||||||
|
|
||||||
fn createTarget(cmd: anytype) !void {
|
fn createTarget(cmd: *CDP.Command) !void {
|
||||||
const params = (try cmd.params(struct {
|
const params = (try cmd.params(struct {
|
||||||
url: [:0]const u8 = "about:blank",
|
url: [:0]const u8 = "about:blank",
|
||||||
// width: ?u64 = null,
|
// width: ?u64 = null,
|
||||||
@@ -230,7 +232,7 @@ fn createTarget(cmd: anytype) !void {
|
|||||||
}, .{});
|
}, .{});
|
||||||
}
|
}
|
||||||
|
|
||||||
fn attachToTarget(cmd: anytype) !void {
|
fn attachToTarget(cmd: *CDP.Command) !void {
|
||||||
const params = (try cmd.params(struct {
|
const params = (try cmd.params(struct {
|
||||||
targetId: []const u8,
|
targetId: []const u8,
|
||||||
flatten: bool = true,
|
flatten: bool = true,
|
||||||
@@ -247,7 +249,7 @@ fn attachToTarget(cmd: anytype) !void {
|
|||||||
return cmd.sendResult(.{ .sessionId = bc.session_id }, .{});
|
return cmd.sendResult(.{ .sessionId = bc.session_id }, .{});
|
||||||
}
|
}
|
||||||
|
|
||||||
fn attachToBrowserTarget(cmd: anytype) !void {
|
fn attachToBrowserTarget(cmd: *CDP.Command) !void {
|
||||||
const bc = cmd.browser_context orelse return error.BrowserContextNotLoaded;
|
const bc = cmd.browser_context orelse return error.BrowserContextNotLoaded;
|
||||||
|
|
||||||
const session_id = bc.session_id orelse cmd.cdp.session_id_gen.next();
|
const session_id = bc.session_id orelse cmd.cdp.session_id_gen.next();
|
||||||
@@ -269,7 +271,7 @@ fn attachToBrowserTarget(cmd: anytype) !void {
|
|||||||
return cmd.sendResult(.{ .sessionId = bc.session_id }, .{});
|
return cmd.sendResult(.{ .sessionId = bc.session_id }, .{});
|
||||||
}
|
}
|
||||||
|
|
||||||
fn closeTarget(cmd: anytype) !void {
|
fn closeTarget(cmd: *CDP.Command) !void {
|
||||||
const params = (try cmd.params(struct {
|
const params = (try cmd.params(struct {
|
||||||
targetId: []const u8,
|
targetId: []const u8,
|
||||||
})) orelse return error.InvalidParams;
|
})) orelse return error.InvalidParams;
|
||||||
@@ -310,7 +312,7 @@ fn closeTarget(cmd: anytype) !void {
|
|||||||
bc.target_id = null;
|
bc.target_id = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn getTargetInfo(cmd: anytype) !void {
|
fn getTargetInfo(cmd: *CDP.Command) !void {
|
||||||
const Params = struct {
|
const Params = struct {
|
||||||
targetId: ?[]const u8 = null,
|
targetId: ?[]const u8 = null,
|
||||||
};
|
};
|
||||||
@@ -347,7 +349,7 @@ fn getTargetInfo(cmd: anytype) !void {
|
|||||||
}, .{ .include_session_id = false });
|
}, .{ .include_session_id = false });
|
||||||
}
|
}
|
||||||
|
|
||||||
fn sendMessageToTarget(cmd: anytype) !void {
|
fn sendMessageToTarget(cmd: *CDP.Command) !void {
|
||||||
const params = (try cmd.params(struct {
|
const params = (try cmd.params(struct {
|
||||||
message: []const u8,
|
message: []const u8,
|
||||||
sessionId: []const u8,
|
sessionId: []const u8,
|
||||||
@@ -365,32 +367,19 @@ fn sendMessageToTarget(cmd: anytype) !void {
|
|||||||
return error.UnknownSessionId;
|
return error.UnknownSessionId;
|
||||||
}
|
}
|
||||||
|
|
||||||
const Capture = struct {
|
var aw = std.Io.Writer.Allocating.init(cmd.arena);
|
||||||
aw: std.Io.Writer.Allocating,
|
cmd.cdp.dispatch(cmd.arena, .{ .capture = &aw.writer }, params.message) catch |err| {
|
||||||
|
|
||||||
pub fn sendJSON(self: *@This(), message: anytype) !void {
|
|
||||||
return std.json.Stringify.value(message, .{
|
|
||||||
.emit_null_optional_fields = false,
|
|
||||||
}, &self.aw.writer);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
var capture = Capture{
|
|
||||||
.aw = .init(cmd.arena),
|
|
||||||
};
|
|
||||||
|
|
||||||
cmd.cdp.dispatch(cmd.arena, &capture, params.message) catch |err| {
|
|
||||||
log.err(.cdp, "internal dispatch error", .{ .err = err, .id = cmd.input.id, .message = params.message });
|
log.err(.cdp, "internal dispatch error", .{ .err = err, .id = cmd.input.id, .message = params.message });
|
||||||
return err;
|
return err;
|
||||||
};
|
};
|
||||||
|
|
||||||
try cmd.sendEvent("Target.receivedMessageFromTarget", .{
|
try cmd.sendEvent("Target.receivedMessageFromTarget", .{
|
||||||
.message = capture.aw.written(),
|
.message = aw.written(),
|
||||||
.sessionId = params.sessionId,
|
.sessionId = params.sessionId,
|
||||||
}, .{});
|
}, .{});
|
||||||
}
|
}
|
||||||
|
|
||||||
fn detachFromTarget(cmd: anytype) !void {
|
fn detachFromTarget(cmd: *CDP.Command) !void {
|
||||||
if (cmd.browser_context) |bc| {
|
if (cmd.browser_context) |bc| {
|
||||||
if (bc.session_id) |session_id| {
|
if (bc.session_id) |session_id| {
|
||||||
try cmd.sendEvent("Target.detachedFromTarget", .{
|
try cmd.sendEvent("Target.detachedFromTarget", .{
|
||||||
@@ -404,11 +393,11 @@ fn detachFromTarget(cmd: anytype) !void {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// TODO: noop method
|
// TODO: noop method
|
||||||
fn setDiscoverTargets(cmd: anytype) !void {
|
fn setDiscoverTargets(cmd: *CDP.Command) !void {
|
||||||
return cmd.sendResult(null, .{});
|
return cmd.sendResult(null, .{});
|
||||||
}
|
}
|
||||||
|
|
||||||
fn setAutoAttach(cmd: anytype) !void {
|
fn setAutoAttach(cmd: *CDP.Command) !void {
|
||||||
const params = (try cmd.params(struct {
|
const params = (try cmd.params(struct {
|
||||||
autoAttach: bool,
|
autoAttach: bool,
|
||||||
waitForDebuggerOnStart: bool,
|
waitForDebuggerOnStart: bool,
|
||||||
@@ -468,7 +457,7 @@ fn setAutoAttach(cmd: anytype) !void {
|
|||||||
try cmd.sendResult(null, .{});
|
try cmd.sendResult(null, .{});
|
||||||
}
|
}
|
||||||
|
|
||||||
fn doAttachtoTarget(cmd: anytype, target_id: []const u8) !void {
|
fn doAttachtoTarget(cmd: *CDP.Command, target_id: []const u8) !void {
|
||||||
const bc = cmd.browser_context.?;
|
const bc = cmd.browser_context.?;
|
||||||
const session_id = bc.session_id orelse cmd.cdp.session_id_gen.next();
|
const session_id = bc.session_id orelse cmd.cdp.session_id_gen.next();
|
||||||
|
|
||||||
|
|||||||
@@ -64,7 +64,7 @@ const TestContext = struct {
|
|||||||
session_id: ?[]const u8 = null,
|
session_id: ?[]const u8 = null,
|
||||||
url: ?[:0]const u8 = null,
|
url: ?[:0]const u8 = null,
|
||||||
};
|
};
|
||||||
pub fn loadBrowserContext(self: *TestContext, opts: BrowserContextOpts) !*CDP.BrowserContext(CDP) {
|
pub fn loadBrowserContext(self: *TestContext, opts: BrowserContextOpts) !*CDP.BrowserContext {
|
||||||
var c = self.cdp();
|
var c = self.cdp();
|
||||||
if (c.browser_context) |bc| {
|
if (c.browser_context) |bc| {
|
||||||
_ = c.disposeBrowserContext(bc.id);
|
_ = c.disposeBrowserContext(bc.id);
|
||||||
|
|||||||
Reference in New Issue
Block a user