Compare commits

...

1 Commits

Author SHA1 Message Date
Karl Seguin
0a04eabc57 Removing remaining CDP generic
Follow up to https://github.com/lightpanda-io/browser/pull/1990 which makes
both BrowserContext and Command non-generic.
2026-03-30 13:04:14 +08:00
19 changed files with 642 additions and 621 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -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,

View File

@@ -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, .{});
} }

View File

@@ -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;

View File

@@ -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;

View File

@@ -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, .{});
} }

View File

@@ -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;

View File

@@ -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;

View File

@@ -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,

View File

@@ -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,

View File

@@ -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,

View File

@@ -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;

View File

@@ -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;

View File

@@ -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,

View File

@@ -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 {

View File

@@ -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;

View File

@@ -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,

View File

@@ -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();

View File

@@ -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);