mirror of
https://github.com/lightpanda-io/browser.git
synced 2026-03-30 17:18:57 +00:00
Compare commits
15 Commits
remove_cdp
...
puppeteer-
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
dd4760858d | ||
|
|
8723ecdd2d | ||
|
|
451178558a | ||
|
|
70dc0f6b95 | ||
|
|
d99599fa21 | ||
|
|
20e62a5551 | ||
|
|
e083d4a3d1 | ||
|
|
7a23686cbd | ||
|
|
25889ff918 | ||
|
|
b4e3f246ca | ||
|
|
f60e5cce6d | ||
|
|
81d4bdb157 | ||
|
|
cf5e4d7d1e | ||
|
|
9f81d7d3ff | ||
|
|
1f22462f13 |
5
.github/workflows/e2e-test.yml
vendored
5
.github/workflows/e2e-test.yml
vendored
@@ -107,8 +107,11 @@ jobs:
|
|||||||
export PROXY_USERNAME=username PROXY_PASSWORD=password
|
export PROXY_USERNAME=username PROXY_PASSWORD=password
|
||||||
./proxy/proxy & echo $! > PROXY.id
|
./proxy/proxy & echo $! > PROXY.id
|
||||||
./lightpanda serve & echo $! > LPD.pid
|
./lightpanda serve & echo $! > LPD.pid
|
||||||
URL=https://demo-browser.lightpanda.io/campfire-commerce/ node puppeteer/proxy_auth.js
|
|
||||||
BASE_URL=https://demo-browser.lightpanda.io/ node playwright/proxy_auth.js
|
BASE_URL=https://demo-browser.lightpanda.io/ node playwright/proxy_auth.js
|
||||||
|
kill `cat LPD.pid`
|
||||||
|
|
||||||
|
./lightpanda serve --http-proxy 'http://127.0.0.1:3000' & echo $! > LPD.pid
|
||||||
|
URL=https://demo-browser.lightpanda.io/campfire-commerce/ node puppeteer/proxy_auth.js
|
||||||
kill `cat LPD.pid` `cat PROXY.id`
|
kill `cat LPD.pid` `cat PROXY.id`
|
||||||
|
|
||||||
# e2e tests w/ web-bot-auth configuration on.
|
# e2e tests w/ web-bot-auth configuration on.
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ const log = @import("log.zig");
|
|||||||
const dump = @import("browser/dump.zig");
|
const dump = @import("browser/dump.zig");
|
||||||
|
|
||||||
const WebBotAuthConfig = @import("network/WebBotAuth.zig").Config;
|
const WebBotAuthConfig = @import("network/WebBotAuth.zig").Config;
|
||||||
|
const mcp = @import("mcp.zig");
|
||||||
|
|
||||||
pub const RunMode = enum {
|
pub const RunMode = enum {
|
||||||
help,
|
help,
|
||||||
@@ -222,6 +223,7 @@ pub const Serve = struct {
|
|||||||
|
|
||||||
pub const Mcp = struct {
|
pub const Mcp = struct {
|
||||||
common: Common = .{},
|
common: Common = .{},
|
||||||
|
version: mcp.Version = .default,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub const DumpFormat = enum {
|
pub const DumpFormat = enum {
|
||||||
@@ -453,6 +455,12 @@ pub fn printUsageAndExit(self: *const Config, success: bool) void {
|
|||||||
\\Starts an MCP (Model Context Protocol) server over stdio
|
\\Starts an MCP (Model Context Protocol) server over stdio
|
||||||
\\Example: {s} mcp
|
\\Example: {s} mcp
|
||||||
\\
|
\\
|
||||||
|
\\Options:
|
||||||
|
\\--version
|
||||||
|
\\ Override the reported MCP version.
|
||||||
|
\\ Valid: 2024-11-05, 2025-03-26, 2025-06-18, 2025-11-25.
|
||||||
|
\\ Defaults to "2024-11-05".
|
||||||
|
\\
|
||||||
++ common_options ++
|
++ common_options ++
|
||||||
\\
|
\\
|
||||||
\\version command
|
\\version command
|
||||||
@@ -640,10 +648,22 @@ fn parseMcpArgs(
|
|||||||
allocator: Allocator,
|
allocator: Allocator,
|
||||||
args: *std.process.ArgIterator,
|
args: *std.process.ArgIterator,
|
||||||
) !Mcp {
|
) !Mcp {
|
||||||
var mcp: Mcp = .{};
|
var result: Mcp = .{};
|
||||||
|
|
||||||
while (args.next()) |opt| {
|
while (args.next()) |opt| {
|
||||||
if (try parseCommonArg(allocator, opt, args, &mcp.common)) {
|
if (std.mem.eql(u8, "--version", opt)) {
|
||||||
|
const str = args.next() orelse {
|
||||||
|
log.fatal(.mcp, "missing argument value", .{ .arg = opt });
|
||||||
|
return error.InvalidArgument;
|
||||||
|
};
|
||||||
|
result.version = std.meta.stringToEnum(mcp.Version, str) orelse {
|
||||||
|
log.fatal(.mcp, "invalid protocol version", .{ .value = str });
|
||||||
|
return error.InvalidArgument;
|
||||||
|
};
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (try parseCommonArg(allocator, opt, args, &result.common)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -651,7 +671,7 @@ fn parseMcpArgs(
|
|||||||
return error.UnkownOption;
|
return error.UnkownOption;
|
||||||
}
|
}
|
||||||
|
|
||||||
return mcp;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parseFetchArgs(
|
fn parseFetchArgs(
|
||||||
|
|||||||
@@ -821,16 +821,16 @@ fn processOneMessage(self: *Client, msg: http.Handles.MultiMessage, transfer: *T
|
|||||||
break :blk std.ascii.eqlIgnoreCase(hdr.value, "close");
|
break :blk std.ascii.eqlIgnoreCase(hdr.value, "close");
|
||||||
};
|
};
|
||||||
|
|
||||||
if (msg.err != null and !is_conn_close_recv) {
|
|
||||||
transfer.requestFailed(transfer._callback_error orelse msg.err.?, true);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// make sure the transfer can't be immediately aborted from a callback
|
// make sure the transfer can't be immediately aborted from a callback
|
||||||
// since we still need it here.
|
// since we still need it here.
|
||||||
transfer._performing = true;
|
transfer._performing = true;
|
||||||
defer transfer._performing = false;
|
defer transfer._performing = false;
|
||||||
|
|
||||||
|
if (msg.err != null and !is_conn_close_recv) {
|
||||||
|
transfer.requestFailed(transfer._callback_error orelse msg.err.?, true);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
if (!transfer._header_done_called) {
|
if (!transfer._header_done_called) {
|
||||||
// In case of request w/o data, we need to call the header done
|
// In case of request w/o data, we need to call the header done
|
||||||
// callback now.
|
// callback now.
|
||||||
@@ -873,7 +873,6 @@ fn processMessages(self: *Client) !bool {
|
|||||||
var processed = false;
|
var processed = false;
|
||||||
while (self.handles.readMessage()) |msg| {
|
while (self.handles.readMessage()) |msg| {
|
||||||
const transfer = try Transfer.fromConnection(&msg.conn);
|
const transfer = try Transfer.fromConnection(&msg.conn);
|
||||||
|
|
||||||
const done = self.processOneMessage(msg, transfer) catch |err| blk: {
|
const done = self.processOneMessage(msg, transfer) catch |err| blk: {
|
||||||
log.err(.http, "process_messages", .{ .err = err, .req = transfer });
|
log.err(.http, "process_messages", .{ .err = err, .req = transfer });
|
||||||
transfer.requestFailed(err, true);
|
transfer.requestFailed(err, true);
|
||||||
@@ -1068,6 +1067,24 @@ pub const Transfer = struct {
|
|||||||
if (self.req.shutdown_callback) |cb| {
|
if (self.req.shutdown_callback) |cb| {
|
||||||
cb(self.ctx);
|
cb(self.ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (self._performing or self.client.performing) {
|
||||||
|
// We're currently inside of a callback. This client, and libcurl
|
||||||
|
// generally don't expect a transfer to become deinitialized during
|
||||||
|
// a callback. We can flag the transfer as aborted (which is what
|
||||||
|
// we do when transfer.abort() is called in this condition) AND,
|
||||||
|
// since this "kill()"should prevent any future callbacks, the best
|
||||||
|
// we can do is null/noop them.
|
||||||
|
self.aborted = true;
|
||||||
|
self.req.start_callback = null;
|
||||||
|
self.req.shutdown_callback = null;
|
||||||
|
self.req.header_callback = Noop.headerCallback;
|
||||||
|
self.req.data_callback = Noop.dataCallback;
|
||||||
|
self.req.done_callback = Noop.doneCallback;
|
||||||
|
self.req.error_callback = Noop.errorCallback;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
self.deinit();
|
self.deinit();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1492,3 +1509,12 @@ pub const Transfer = struct {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const Noop = struct {
|
||||||
|
fn headerCallback(_: *Transfer) !bool {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
fn dataCallback(_: *Transfer, _: []const u8) !void {}
|
||||||
|
fn doneCallback(_: *anyopaque) !void {}
|
||||||
|
fn errorCallback(_: *anyopaque, _: anyerror) void {}
|
||||||
|
};
|
||||||
|
|||||||
@@ -148,3 +148,13 @@
|
|||||||
|
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
<script id=identity>
|
||||||
|
{
|
||||||
|
const element = document.createElement('canvas');
|
||||||
|
const ctx = element.getContext('2d');
|
||||||
|
|
||||||
|
testing.expectTrue(ctx === element.getContext('2d'));
|
||||||
|
testing.expectEqual(null, element.getContext('webgl'));
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|||||||
@@ -85,3 +85,13 @@
|
|||||||
loseContext.restoreContext();
|
loseContext.restoreContext();
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
<script id=identity>
|
||||||
|
{
|
||||||
|
const element = document.createElement('canvas');
|
||||||
|
const ctx = element.getContext('webgl');
|
||||||
|
|
||||||
|
testing.expectTrue(ctx === element.getContext('webgl'));
|
||||||
|
testing.expectEqual(null, element.getContext('2d'));
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|||||||
@@ -59,6 +59,7 @@ pub fn fromError(err: anyerror) ?DOMException {
|
|||||||
error.TimeoutError => .{ ._code = .timeout_error },
|
error.TimeoutError => .{ ._code = .timeout_error },
|
||||||
error.InvalidNodeType => .{ ._code = .invalid_node_type_error },
|
error.InvalidNodeType => .{ ._code = .invalid_node_type_error },
|
||||||
error.DataClone => .{ ._code = .data_clone_error },
|
error.DataClone => .{ ._code = .data_clone_error },
|
||||||
|
error.InvalidAccessError => .{ ._code = .invalid_access_error },
|
||||||
else => null,
|
else => null,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,6 +29,9 @@ const OffscreenCanvas = @import("../../canvas/OffscreenCanvas.zig");
|
|||||||
|
|
||||||
const Canvas = @This();
|
const Canvas = @This();
|
||||||
_proto: *HtmlElement,
|
_proto: *HtmlElement,
|
||||||
|
_cached: ?DrawingContext = null,
|
||||||
|
|
||||||
|
const ContextType = enum { none, @"2d", webgl };
|
||||||
|
|
||||||
pub fn asElement(self: *Canvas) *Element {
|
pub fn asElement(self: *Canvas) *Element {
|
||||||
return self._proto._proto;
|
return self._proto._proto;
|
||||||
@@ -68,17 +71,28 @@ const DrawingContext = union(enum) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
pub fn getContext(self: *Canvas, context_type: []const u8, page: *Page) !?DrawingContext {
|
pub fn getContext(self: *Canvas, context_type: []const u8, page: *Page) !?DrawingContext {
|
||||||
if (std.mem.eql(u8, context_type, "2d")) {
|
if (self._cached) |cached| {
|
||||||
const ctx = try page._factory.create(CanvasRenderingContext2D{ ._canvas = self });
|
const matches = switch (cached) {
|
||||||
return .{ .@"2d" = ctx };
|
.@"2d" => std.mem.eql(u8, context_type, "2d"),
|
||||||
|
.webgl => std.mem.eql(u8, context_type, "webgl") or std.mem.eql(u8, context_type, "experimental-webgl"),
|
||||||
|
};
|
||||||
|
return if (matches) cached else null;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (std.mem.eql(u8, context_type, "webgl") or std.mem.eql(u8, context_type, "experimental-webgl")) {
|
const drawing_context: DrawingContext = blk: {
|
||||||
const ctx = try page._factory.create(WebGLRenderingContext{});
|
if (std.mem.eql(u8, context_type, "2d")) {
|
||||||
return .{ .webgl = ctx };
|
const ctx = try page._factory.create(CanvasRenderingContext2D{ ._canvas = self });
|
||||||
}
|
break :blk .{ .@"2d" = ctx };
|
||||||
|
}
|
||||||
|
|
||||||
return null;
|
if (std.mem.eql(u8, context_type, "webgl") or std.mem.eql(u8, context_type, "experimental-webgl")) {
|
||||||
|
const ctx = try page._factory.create(WebGLRenderingContext{});
|
||||||
|
break :blk .{ .webgl = ctx };
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
};
|
||||||
|
self._cached = drawing_context;
|
||||||
|
return drawing_context;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Transfers control of the canvas to an OffscreenCanvas.
|
/// Transfers control of the canvas to an OffscreenCanvas.
|
||||||
|
|||||||
955
src/cdp/CDP.zig
955
src/cdp/CDP.zig
File diff suppressed because it is too large
Load Diff
@@ -18,9 +18,8 @@
|
|||||||
|
|
||||||
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: *CDP.Command) !void {
|
pub fn processMessage(cmd: anytype) !void {
|
||||||
const action = std.meta.stringToEnum(enum {
|
const action = std.meta.stringToEnum(enum {
|
||||||
enable,
|
enable,
|
||||||
disable,
|
disable,
|
||||||
@@ -33,15 +32,15 @@ pub fn processMessage(cmd: *CDP.Command) !void {
|
|||||||
.getFullAXTree => return getFullAXTree(cmd),
|
.getFullAXTree => return getFullAXTree(cmd),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn enable(cmd: *CDP.Command) !void {
|
fn enable(cmd: anytype) !void {
|
||||||
return cmd.sendResult(null, .{});
|
return cmd.sendResult(null, .{});
|
||||||
}
|
}
|
||||||
|
|
||||||
fn disable(cmd: *CDP.Command) !void {
|
fn disable(cmd: anytype) !void {
|
||||||
return cmd.sendResult(null, .{});
|
return cmd.sendResult(null, .{});
|
||||||
}
|
}
|
||||||
|
|
||||||
fn getFullAXTree(cmd: *CDP.Command) !void {
|
fn getFullAXTree(cmd: anytype) !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,7 +17,6 @@
|
|||||||
// 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";
|
||||||
@@ -36,7 +35,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: *CDP.Command) !void {
|
pub fn processMessage(cmd: anytype) !void {
|
||||||
const action = std.meta.stringToEnum(enum {
|
const action = std.meta.stringToEnum(enum {
|
||||||
getVersion,
|
getVersion,
|
||||||
setPermission,
|
setPermission,
|
||||||
@@ -58,7 +57,7 @@ pub fn processMessage(cmd: *CDP.Command) !void {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn getVersion(cmd: *CDP.Command) !void {
|
fn getVersion(cmd: anytype) !void {
|
||||||
// TODO: pre-serialize?
|
// TODO: pre-serialize?
|
||||||
return cmd.sendResult(.{
|
return cmd.sendResult(.{
|
||||||
.protocolVersion = PROTOCOL_VERSION,
|
.protocolVersion = PROTOCOL_VERSION,
|
||||||
@@ -70,7 +69,7 @@ fn getVersion(cmd: *CDP.Command) !void {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// TODO: noop method
|
// TODO: noop method
|
||||||
fn setDownloadBehavior(cmd: *CDP.Command) !void {
|
fn setDownloadBehavior(cmd: anytype) !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,
|
||||||
@@ -81,7 +80,7 @@ fn setDownloadBehavior(cmd: *CDP.Command) !void {
|
|||||||
return cmd.sendResult(null, .{ .include_session_id = false });
|
return cmd.sendResult(null, .{ .include_session_id = false });
|
||||||
}
|
}
|
||||||
|
|
||||||
fn getWindowForTarget(cmd: *CDP.Command) !void {
|
fn getWindowForTarget(cmd: anytype) !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;
|
||||||
@@ -92,22 +91,22 @@ fn getWindowForTarget(cmd: *CDP.Command) !void {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// TODO: noop method
|
// TODO: noop method
|
||||||
fn setWindowBounds(cmd: *CDP.Command) !void {
|
fn setWindowBounds(cmd: anytype) !void {
|
||||||
return cmd.sendResult(null, .{});
|
return cmd.sendResult(null, .{});
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: noop method
|
// TODO: noop method
|
||||||
fn grantPermissions(cmd: *CDP.Command) !void {
|
fn grantPermissions(cmd: anytype) !void {
|
||||||
return cmd.sendResult(null, .{});
|
return cmd.sendResult(null, .{});
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: noop method
|
// TODO: noop method
|
||||||
fn setPermission(cmd: *CDP.Command) !void {
|
fn setPermission(cmd: anytype) !void {
|
||||||
return cmd.sendResult(null, .{});
|
return cmd.sendResult(null, .{});
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: noop method
|
// TODO: noop method
|
||||||
fn resetPermissions(cmd: *CDP.Command) !void {
|
fn resetPermissions(cmd: anytype) !void {
|
||||||
return cmd.sendResult(null, .{});
|
return cmd.sendResult(null, .{});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -17,9 +17,8 @@
|
|||||||
// 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: *CDP.Command) !void {
|
pub fn processMessage(cmd: anytype) !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,18 +18,17 @@
|
|||||||
|
|
||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
const id = @import("../id.zig");
|
const id = @import("../id.zig");
|
||||||
const CDP = @import("../CDP.zig");
|
|
||||||
const Node = @import("../Node.zig");
|
|
||||||
|
|
||||||
const log = @import("../../log.zig");
|
const log = @import("../../log.zig");
|
||||||
const dump = @import("../../browser/dump.zig");
|
const Node = @import("../Node.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: *CDP.Command) !void {
|
pub fn processMessage(cmd: anytype) !void {
|
||||||
const action = std.meta.stringToEnum(enum {
|
const action = std.meta.stringToEnum(enum {
|
||||||
enable,
|
enable,
|
||||||
getDocument,
|
getDocument,
|
||||||
@@ -70,7 +69,7 @@ pub fn processMessage(cmd: *CDP.Command) !void {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// https://chromedevtools.github.io/devtools-protocol/tot/DOM/#method-getDocument
|
// https://chromedevtools.github.io/devtools-protocol/tot/DOM/#method-getDocument
|
||||||
fn getDocument(cmd: *CDP.Command) !void {
|
fn getDocument(cmd: anytype) !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,
|
||||||
@@ -90,7 +89,7 @@ fn getDocument(cmd: *CDP.Command) !void {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// https://chromedevtools.github.io/devtools-protocol/tot/DOM/#method-performSearch
|
// https://chromedevtools.github.io/devtools-protocol/tot/DOM/#method-performSearch
|
||||||
fn performSearch(cmd: *CDP.Command) !void {
|
fn performSearch(cmd: anytype) !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,
|
||||||
@@ -117,7 +116,7 @@ fn performSearch(cmd: *CDP.Command) !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: *CDP.Command, dom_nodes: []const *DOMNode) !void {
|
fn dispatchSetChildNodes(cmd: anytype, 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;
|
||||||
@@ -173,7 +172,7 @@ fn dispatchSetChildNodes(cmd: *CDP.Command, 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: *CDP.Command) !void {
|
fn discardSearchResults(cmd: anytype) !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;
|
||||||
@@ -185,7 +184,7 @@ fn discardSearchResults(cmd: *CDP.Command) !void {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// https://chromedevtools.github.io/devtools-protocol/tot/DOM/#method-getSearchResults
|
// https://chromedevtools.github.io/devtools-protocol/tot/DOM/#method-getSearchResults
|
||||||
fn getSearchResults(cmd: *CDP.Command) !void {
|
fn getSearchResults(cmd: anytype) !void {
|
||||||
const params = (try cmd.params(struct {
|
const params = (try cmd.params(struct {
|
||||||
searchId: []const u8,
|
searchId: []const u8,
|
||||||
fromIndex: u32,
|
fromIndex: u32,
|
||||||
@@ -210,7 +209,7 @@ fn getSearchResults(cmd: *CDP.Command) !void {
|
|||||||
return cmd.sendResult(.{ .nodeIds = node_ids[params.fromIndex..params.toIndex] }, .{});
|
return cmd.sendResult(.{ .nodeIds = node_ids[params.fromIndex..params.toIndex] }, .{});
|
||||||
}
|
}
|
||||||
|
|
||||||
fn querySelector(cmd: *CDP.Command) !void {
|
fn querySelector(cmd: anytype) !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,
|
||||||
@@ -236,7 +235,7 @@ fn querySelector(cmd: *CDP.Command) !void {
|
|||||||
}, .{});
|
}, .{});
|
||||||
}
|
}
|
||||||
|
|
||||||
fn querySelectorAll(cmd: *CDP.Command) !void {
|
fn querySelectorAll(cmd: anytype) !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,
|
||||||
@@ -267,7 +266,7 @@ fn querySelectorAll(cmd: *CDP.Command) !void {
|
|||||||
}, .{});
|
}, .{});
|
||||||
}
|
}
|
||||||
|
|
||||||
fn resolveNode(cmd: *CDP.Command) !void {
|
fn resolveNode(cmd: anytype) !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,
|
||||||
@@ -328,7 +327,7 @@ fn resolveNode(cmd: *CDP.Command) !void {
|
|||||||
} }, .{});
|
} }, .{});
|
||||||
}
|
}
|
||||||
|
|
||||||
fn describeNode(cmd: *CDP.Command) !void {
|
fn describeNode(cmd: anytype) !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,
|
||||||
@@ -375,7 +374,7 @@ fn rectToQuad(rect: DOMNode.Element.DOMRect) Quad {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
fn scrollIntoViewIfNeeded(cmd: *CDP.Command) !void {
|
fn scrollIntoViewIfNeeded(cmd: anytype) !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,
|
||||||
@@ -398,7 +397,7 @@ fn scrollIntoViewIfNeeded(cmd: *CDP.Command) !void {
|
|||||||
return cmd.sendResult(null, .{});
|
return cmd.sendResult(null, .{});
|
||||||
}
|
}
|
||||||
|
|
||||||
fn getNode(arena: Allocator, bc: *CDP.BrowserContext, node_id: ?Node.Id, backend_node_id: ?Node.Id, object_id: ?[]const u8) !*Node {
|
fn getNode(arena: Allocator, bc: anytype, 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;
|
||||||
@@ -418,7 +417,7 @@ fn getNode(arena: Allocator, bc: *CDP.BrowserContext, node_id: ?Node.Id, backend
|
|||||||
|
|
||||||
// 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: *CDP.Command) !void {
|
fn getContentQuads(cmd: anytype) !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,
|
||||||
@@ -444,7 +443,7 @@ fn getContentQuads(cmd: *CDP.Command) !void {
|
|||||||
return cmd.sendResult(.{ .quads = &.{quad} }, .{});
|
return cmd.sendResult(.{ .quads = &.{quad} }, .{});
|
||||||
}
|
}
|
||||||
|
|
||||||
fn getBoxModel(cmd: *CDP.Command) !void {
|
fn getBoxModel(cmd: anytype) !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,
|
||||||
@@ -473,7 +472,7 @@ fn getBoxModel(cmd: *CDP.Command) !void {
|
|||||||
} }, .{});
|
} }, .{});
|
||||||
}
|
}
|
||||||
|
|
||||||
fn requestChildNodes(cmd: *CDP.Command) !void {
|
fn requestChildNodes(cmd: anytype) !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,
|
||||||
@@ -497,7 +496,7 @@ fn requestChildNodes(cmd: *CDP.Command) !void {
|
|||||||
return cmd.sendResult(null, .{});
|
return cmd.sendResult(null, .{});
|
||||||
}
|
}
|
||||||
|
|
||||||
fn getFrameOwner(cmd: *CDP.Command) !void {
|
fn getFrameOwner(cmd: anytype) !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;
|
||||||
@@ -513,7 +512,7 @@ fn getFrameOwner(cmd: *CDP.Command) !void {
|
|||||||
return cmd.sendResult(.{ .nodeId = node.id, .backendNodeId = node.id }, .{});
|
return cmd.sendResult(.{ .nodeId = node.id, .backendNodeId = node.id }, .{});
|
||||||
}
|
}
|
||||||
|
|
||||||
fn getOuterHTML(cmd: *CDP.Command) !void {
|
fn getOuterHTML(cmd: anytype) !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,
|
||||||
@@ -535,7 +534,7 @@ fn getOuterHTML(cmd: *CDP.Command) !void {
|
|||||||
return cmd.sendResult(.{ .outerHTML = aw.written() }, .{});
|
return cmd.sendResult(.{ .outerHTML = aw.written() }, .{});
|
||||||
}
|
}
|
||||||
|
|
||||||
fn requestNode(cmd: *CDP.Command) !void {
|
fn requestNode(cmd: anytype) !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,10 +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");
|
|
||||||
const log = @import("../../log.zig");
|
const log = @import("../../log.zig");
|
||||||
|
|
||||||
pub fn processMessage(cmd: *CDP.Command) !void {
|
pub fn processMessage(cmd: anytype) !void {
|
||||||
const action = std.meta.stringToEnum(enum {
|
const action = std.meta.stringToEnum(enum {
|
||||||
setEmulatedMedia,
|
setEmulatedMedia,
|
||||||
setFocusEmulationEnabled,
|
setFocusEmulationEnabled,
|
||||||
@@ -39,7 +38,7 @@ pub fn processMessage(cmd: *CDP.Command) !void {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// TODO: noop method
|
// TODO: noop method
|
||||||
fn setEmulatedMedia(cmd: *CDP.Command) !void {
|
fn setEmulatedMedia(cmd: anytype) !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{
|
||||||
@@ -52,7 +51,7 @@ fn setEmulatedMedia(cmd: *CDP.Command) !void {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// TODO: noop method
|
// TODO: noop method
|
||||||
fn setFocusEmulationEnabled(cmd: *CDP.Command) !void {
|
fn setFocusEmulationEnabled(cmd: anytype) !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;
|
||||||
@@ -60,16 +59,16 @@ fn setFocusEmulationEnabled(cmd: *CDP.Command) !void {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// TODO: noop method
|
// TODO: noop method
|
||||||
fn setDeviceMetricsOverride(cmd: *CDP.Command) !void {
|
fn setDeviceMetricsOverride(cmd: anytype) !void {
|
||||||
return cmd.sendResult(null, .{});
|
return cmd.sendResult(null, .{});
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: noop method
|
// TODO: noop method
|
||||||
fn setTouchEmulationEnabled(cmd: *CDP.Command) !void {
|
fn setTouchEmulationEnabled(cmd: anytype) !void {
|
||||||
return cmd.sendResult(null, .{});
|
return cmd.sendResult(null, .{});
|
||||||
}
|
}
|
||||||
|
|
||||||
fn setUserAgentOverride(cmd: *CDP.Command) !void {
|
fn setUserAgentOverride(cmd: anytype) !void {
|
||||||
log.info(.app, "setUserAgentOverride ignored", .{});
|
log.info(.app, "setUserAgentOverride ignored", .{});
|
||||||
return cmd.sendResult(null, .{});
|
return cmd.sendResult(null, .{});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,19 +17,17 @@
|
|||||||
// 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");
|
||||||
|
|
||||||
const network = @import("network.zig");
|
pub fn processMessage(cmd: anytype) !void {
|
||||||
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,
|
||||||
@@ -137,13 +135,13 @@ const ErrorReason = enum {
|
|||||||
BlockedByResponse,
|
BlockedByResponse,
|
||||||
};
|
};
|
||||||
|
|
||||||
fn disable(cmd: *CDP.Command) !void {
|
fn disable(cmd: anytype) !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: *CDP.Command) !void {
|
fn enable(cmd: anytype) !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" });
|
||||||
@@ -182,7 +180,7 @@ fn arePatternsSupported(patterns: []RequestPattern) bool {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn requestIntercept(bc: *CDP.BrowserContext, intercept: *const Notification.RequestIntercept) !void {
|
pub fn requestIntercept(bc: anytype, 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;
|
||||||
@@ -217,7 +215,7 @@ pub fn requestIntercept(bc: *CDP.BrowserContext, intercept: *const Notification.
|
|||||||
intercept.wait_for_interception.* = true;
|
intercept.wait_for_interception.* = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn continueRequest(cmd: *CDP.Command) !void {
|
fn continueRequest(cmd: anytype) !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}"
|
||||||
@@ -277,7 +275,7 @@ const AuthChallengeResponse = enum {
|
|||||||
ProvideCredentials,
|
ProvideCredentials,
|
||||||
};
|
};
|
||||||
|
|
||||||
fn continueWithAuth(cmd: *CDP.Command) !void {
|
fn continueWithAuth(cmd: anytype) !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}"
|
||||||
@@ -320,7 +318,7 @@ fn continueWithAuth(cmd: *CDP.Command) !void {
|
|||||||
return cmd.sendResult(null, .{});
|
return cmd.sendResult(null, .{});
|
||||||
}
|
}
|
||||||
|
|
||||||
fn fulfillRequest(cmd: *CDP.Command) !void {
|
fn fulfillRequest(cmd: anytype) !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 {
|
||||||
@@ -362,7 +360,7 @@ fn fulfillRequest(cmd: *CDP.Command) !void {
|
|||||||
return cmd.sendResult(null, .{});
|
return cmd.sendResult(null, .{});
|
||||||
}
|
}
|
||||||
|
|
||||||
fn failRequest(cmd: *CDP.Command) !void {
|
fn failRequest(cmd: anytype) !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}"
|
||||||
@@ -384,7 +382,7 @@ fn failRequest(cmd: *CDP.Command) !void {
|
|||||||
return cmd.sendResult(null, .{});
|
return cmd.sendResult(null, .{});
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn requestAuthRequired(bc: *CDP.BrowserContext, intercept: *const Notification.RequestAuthRequired) !void {
|
pub fn requestAuthRequired(bc: anytype, 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,9 +17,8 @@
|
|||||||
// 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: *CDP.Command) !void {
|
pub fn processMessage(cmd: anytype) !void {
|
||||||
const action = std.meta.stringToEnum(enum {
|
const action = std.meta.stringToEnum(enum {
|
||||||
dispatchKeyEvent,
|
dispatchKeyEvent,
|
||||||
dispatchMouseEvent,
|
dispatchMouseEvent,
|
||||||
@@ -34,7 +33,7 @@ pub fn processMessage(cmd: *CDP.Command) !void {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// https://chromedevtools.github.io/devtools-protocol/tot/Input/#method-dispatchKeyEvent
|
// https://chromedevtools.github.io/devtools-protocol/tot/Input/#method-dispatchKeyEvent
|
||||||
fn dispatchKeyEvent(cmd: *CDP.Command) !void {
|
fn dispatchKeyEvent(cmd: anytype) !void {
|
||||||
const params = (try cmd.params(struct {
|
const params = (try cmd.params(struct {
|
||||||
type: Type,
|
type: Type,
|
||||||
key: []const u8 = "",
|
key: []const u8 = "",
|
||||||
@@ -75,7 +74,7 @@ fn dispatchKeyEvent(cmd: *CDP.Command) !void {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// https://chromedevtools.github.io/devtools-protocol/tot/Input/#method-dispatchMouseEvent
|
// https://chromedevtools.github.io/devtools-protocol/tot/Input/#method-dispatchMouseEvent
|
||||||
fn dispatchMouseEvent(cmd: *CDP.Command) !void {
|
fn dispatchMouseEvent(cmd: anytype) !void {
|
||||||
const params = (try cmd.params(struct {
|
const params = (try cmd.params(struct {
|
||||||
x: f64,
|
x: f64,
|
||||||
y: f64,
|
y: f64,
|
||||||
@@ -105,7 +104,7 @@ fn dispatchMouseEvent(cmd: *CDP.Command) !void {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// https://chromedevtools.github.io/devtools-protocol/tot/Input/#method-insertText
|
// https://chromedevtools.github.io/devtools-protocol/tot/Input/#method-insertText
|
||||||
fn insertText(cmd: *CDP.Command) !void {
|
fn insertText(cmd: anytype) !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,9 +17,8 @@
|
|||||||
// 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: *CDP.Command) !void {
|
pub fn processMessage(cmd: anytype) !void {
|
||||||
const action = std.meta.stringToEnum(enum {
|
const action = std.meta.stringToEnum(enum {
|
||||||
enable,
|
enable,
|
||||||
disable,
|
disable,
|
||||||
|
|||||||
@@ -17,9 +17,8 @@
|
|||||||
// 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: *CDP.Command) !void {
|
pub fn processMessage(cmd: anytype) !void {
|
||||||
const action = std.meta.stringToEnum(enum {
|
const action = std.meta.stringToEnum(enum {
|
||||||
enable,
|
enable,
|
||||||
disable,
|
disable,
|
||||||
|
|||||||
@@ -18,18 +18,14 @@
|
|||||||
|
|
||||||
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: *CDP.Command) !void {
|
pub fn processMessage(cmd: anytype) !void {
|
||||||
const action = std.meta.stringToEnum(enum {
|
const action = std.meta.stringToEnum(enum {
|
||||||
getMarkdown,
|
getMarkdown,
|
||||||
getSemanticTree,
|
getSemanticTree,
|
||||||
@@ -55,7 +51,7 @@ pub fn processMessage(cmd: *CDP.Command) !void {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn getSemanticTree(cmd: *CDP.Command) !void {
|
fn getSemanticTree(cmd: anytype) !void {
|
||||||
const Params = struct {
|
const Params = struct {
|
||||||
format: ?enum { text } = null,
|
format: ?enum { text } = null,
|
||||||
prune: ?bool = null,
|
prune: ?bool = null,
|
||||||
@@ -100,7 +96,7 @@ fn getSemanticTree(cmd: *CDP.Command) !void {
|
|||||||
}, .{});
|
}, .{});
|
||||||
}
|
}
|
||||||
|
|
||||||
fn getMarkdown(cmd: *CDP.Command) !void {
|
fn getMarkdown(cmd: anytype) !void {
|
||||||
const Params = struct {
|
const Params = struct {
|
||||||
nodeId: ?Node.Id = null,
|
nodeId: ?Node.Id = null,
|
||||||
};
|
};
|
||||||
@@ -123,7 +119,7 @@ fn getMarkdown(cmd: *CDP.Command) !void {
|
|||||||
}, .{});
|
}, .{});
|
||||||
}
|
}
|
||||||
|
|
||||||
fn getInteractiveElements(cmd: *CDP.Command) !void {
|
fn getInteractiveElements(cmd: anytype) !void {
|
||||||
const Params = struct {
|
const Params = struct {
|
||||||
nodeId: ?Node.Id = null,
|
nodeId: ?Node.Id = null,
|
||||||
};
|
};
|
||||||
@@ -145,7 +141,7 @@ fn getInteractiveElements(cmd: *CDP.Command) !void {
|
|||||||
}, .{});
|
}, .{});
|
||||||
}
|
}
|
||||||
|
|
||||||
fn getStructuredData(cmd: *CDP.Command) !void {
|
fn getStructuredData(cmd: anytype) !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;
|
||||||
|
|
||||||
@@ -160,7 +156,7 @@ fn getStructuredData(cmd: *CDP.Command) !void {
|
|||||||
}, .{});
|
}, .{});
|
||||||
}
|
}
|
||||||
|
|
||||||
fn detectForms(cmd: *CDP.Command) !void {
|
fn detectForms(cmd: anytype) !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;
|
||||||
|
|
||||||
@@ -177,7 +173,7 @@ fn detectForms(cmd: *CDP.Command) !void {
|
|||||||
}, .{});
|
}, .{});
|
||||||
}
|
}
|
||||||
|
|
||||||
fn clickNode(cmd: *CDP.Command) !void {
|
fn clickNode(cmd: anytype) !void {
|
||||||
const Params = struct {
|
const Params = struct {
|
||||||
nodeId: ?Node.Id = null,
|
nodeId: ?Node.Id = null,
|
||||||
backendNodeId: ?Node.Id = null,
|
backendNodeId: ?Node.Id = null,
|
||||||
@@ -198,7 +194,7 @@ fn clickNode(cmd: *CDP.Command) !void {
|
|||||||
return cmd.sendResult(.{}, .{});
|
return cmd.sendResult(.{}, .{});
|
||||||
}
|
}
|
||||||
|
|
||||||
fn fillNode(cmd: *CDP.Command) !void {
|
fn fillNode(cmd: anytype) !void {
|
||||||
const Params = struct {
|
const Params = struct {
|
||||||
nodeId: ?Node.Id = null,
|
nodeId: ?Node.Id = null,
|
||||||
backendNodeId: ?Node.Id = null,
|
backendNodeId: ?Node.Id = null,
|
||||||
@@ -220,7 +216,7 @@ fn fillNode(cmd: *CDP.Command) !void {
|
|||||||
return cmd.sendResult(.{}, .{});
|
return cmd.sendResult(.{}, .{});
|
||||||
}
|
}
|
||||||
|
|
||||||
fn scrollNode(cmd: *CDP.Command) !void {
|
fn scrollNode(cmd: anytype) !void {
|
||||||
const Params = struct {
|
const Params = struct {
|
||||||
nodeId: ?Node.Id = null,
|
nodeId: ?Node.Id = null,
|
||||||
backendNodeId: ?Node.Id = null,
|
backendNodeId: ?Node.Id = null,
|
||||||
@@ -248,7 +244,7 @@ fn scrollNode(cmd: *CDP.Command) !void {
|
|||||||
return cmd.sendResult(.{}, .{});
|
return cmd.sendResult(.{}, .{});
|
||||||
}
|
}
|
||||||
|
|
||||||
fn waitForSelector(cmd: *CDP.Command) !void {
|
fn waitForSelector(cmd: anytype) !void {
|
||||||
const Params = struct {
|
const Params = struct {
|
||||||
selector: []const u8,
|
selector: []const u8,
|
||||||
timeout: ?u32 = null,
|
timeout: ?u32 = null,
|
||||||
|
|||||||
@@ -18,21 +18,18 @@
|
|||||||
|
|
||||||
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 id = @import("../id.zig");
|
const CdpStorage = @import("storage.zig");
|
||||||
const CDP = @import("../CDP.zig");
|
|
||||||
|
|
||||||
|
const id = @import("../id.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");
|
||||||
|
|
||||||
const CdpStorage = @import("storage.zig");
|
pub fn processMessage(cmd: anytype) !void {
|
||||||
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,
|
||||||
@@ -62,19 +59,19 @@ pub fn processMessage(cmd: *CDP.Command) !void {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn enable(cmd: *CDP.Command) !void {
|
fn enable(cmd: anytype) !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: *CDP.Command) !void {
|
fn disable(cmd: anytype) !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: *CDP.Command) !void {
|
fn setExtraHTTPHeaders(cmd: anytype) !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;
|
||||||
@@ -113,7 +110,7 @@ fn cookieMatches(cookie: *const Cookie, name: []const u8, domain: ?[]const u8, p
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn deleteCookies(cmd: *CDP.Command) !void {
|
fn deleteCookies(cmd: anytype) !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,
|
||||||
@@ -147,14 +144,14 @@ fn deleteCookies(cmd: *CDP.Command) !void {
|
|||||||
return cmd.sendResult(null, .{});
|
return cmd.sendResult(null, .{});
|
||||||
}
|
}
|
||||||
|
|
||||||
fn clearBrowserCookies(cmd: *CDP.Command) !void {
|
fn clearBrowserCookies(cmd: anytype) !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: *CDP.Command) !void {
|
fn setCookie(cmd: anytype) !void {
|
||||||
const params = (try cmd.params(
|
const params = (try cmd.params(
|
||||||
CdpStorage.CdpCookie,
|
CdpStorage.CdpCookie,
|
||||||
)) orelse return error.InvalidParams;
|
)) orelse return error.InvalidParams;
|
||||||
@@ -165,7 +162,7 @@ fn setCookie(cmd: *CDP.Command) !void {
|
|||||||
try cmd.sendResult(.{ .success = true }, .{});
|
try cmd.sendResult(.{ .success = true }, .{});
|
||||||
}
|
}
|
||||||
|
|
||||||
fn setCookies(cmd: *CDP.Command) !void {
|
fn setCookies(cmd: anytype) !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;
|
||||||
@@ -181,7 +178,7 @@ fn setCookies(cmd: *CDP.Command) !void {
|
|||||||
const GetCookiesParam = struct {
|
const GetCookiesParam = struct {
|
||||||
urls: ?[]const [:0]const u8 = null,
|
urls: ?[]const [:0]const u8 = null,
|
||||||
};
|
};
|
||||||
fn getCookies(cmd: *CDP.Command) !void {
|
fn getCookies(cmd: anytype) !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{};
|
||||||
|
|
||||||
@@ -204,7 +201,7 @@ fn getCookies(cmd: *CDP.Command) !void {
|
|||||||
try cmd.sendResult(.{ .cookies = writer }, .{});
|
try cmd.sendResult(.{ .cookies = writer }, .{});
|
||||||
}
|
}
|
||||||
|
|
||||||
fn getResponseBody(cmd: *CDP.Command) !void {
|
fn getResponseBody(cmd: anytype) !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;
|
||||||
@@ -230,7 +227,7 @@ fn getResponseBody(cmd: *CDP.Command) !void {
|
|||||||
}, .{});
|
}, .{});
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn httpRequestFail(bc: *CDP.BrowserContext, msg: *const Notification.RequestFail) !void {
|
pub fn httpRequestFail(bc: anytype, 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.
|
||||||
@@ -250,7 +247,7 @@ pub fn httpRequestFail(bc: *CDP.BrowserContext, msg: *const Notification.Request
|
|||||||
}, .{ .session_id = session_id });
|
}, .{ .session_id = session_id });
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn httpRequestStart(bc: *CDP.BrowserContext, msg: *const Notification.RequestStart) !void {
|
pub fn httpRequestStart(bc: anytype, 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;
|
||||||
@@ -279,7 +276,7 @@ pub fn httpRequestStart(bc: *CDP.BrowserContext, msg: *const Notification.Reques
|
|||||||
}, .{ .session_id = session_id });
|
}, .{ .session_id = session_id });
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn httpResponseHeaderDone(arena: Allocator, bc: *CDP.BrowserContext, msg: *const Notification.ResponseHeaderDone) !void {
|
pub fn httpResponseHeaderDone(arena: Allocator, bc: anytype, 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;
|
||||||
@@ -296,7 +293,7 @@ pub fn httpResponseHeaderDone(arena: Allocator, bc: *CDP.BrowserContext, msg: *c
|
|||||||
}, .{ .session_id = session_id });
|
}, .{ .session_id = session_id });
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn httpRequestDone(bc: *CDP.BrowserContext, msg: *const Notification.RequestDone) !void {
|
pub fn httpRequestDone(bc: anytype, 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,5 +1,4 @@
|
|||||||
// 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>
|
||||||
@@ -23,8 +22,6 @@ 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");
|
||||||
@@ -34,7 +31,7 @@ const Notification = @import("../../Notification.zig");
|
|||||||
|
|
||||||
const Allocator = std.mem.Allocator;
|
const Allocator = std.mem.Allocator;
|
||||||
|
|
||||||
pub fn processMessage(cmd: *CDP.Command) !void {
|
pub fn processMessage(cmd: anytype) !void {
|
||||||
const action = std.meta.stringToEnum(enum {
|
const action = std.meta.stringToEnum(enum {
|
||||||
enable,
|
enable,
|
||||||
getFrameTree,
|
getFrameTree,
|
||||||
@@ -81,7 +78,7 @@ const Frame = struct {
|
|||||||
gatedAPIFeatures: [][]const u8 = &[0][]const u8{},
|
gatedAPIFeatures: [][]const u8 = &[0][]const u8{},
|
||||||
};
|
};
|
||||||
|
|
||||||
fn getFrameTree(cmd: *CDP.Command) !void {
|
fn getFrameTree(cmd: anytype) !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 = .{
|
||||||
@@ -111,7 +108,7 @@ fn getFrameTree(cmd: *CDP.Command) !void {
|
|||||||
}, .{});
|
}, .{});
|
||||||
}
|
}
|
||||||
|
|
||||||
fn setLifecycleEventsEnabled(cmd: *CDP.Command) !void {
|
fn setLifecycleEventsEnabled(cmd: anytype) !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;
|
||||||
@@ -152,7 +149,7 @@ fn setLifecycleEventsEnabled(cmd: *CDP.Command) !void {
|
|||||||
return cmd.sendResult(null, .{});
|
return cmd.sendResult(null, .{});
|
||||||
}
|
}
|
||||||
|
|
||||||
fn addScriptToEvaluateOnNewDocument(cmd: *CDP.Command) !void {
|
fn addScriptToEvaluateOnNewDocument(cmd: anytype) !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,
|
||||||
@@ -182,7 +179,7 @@ fn addScriptToEvaluateOnNewDocument(cmd: *CDP.Command) !void {
|
|||||||
}, .{});
|
}, .{});
|
||||||
}
|
}
|
||||||
|
|
||||||
fn removeScriptToEvaluateOnNewDocument(cmd: *CDP.Command) !void {
|
fn removeScriptToEvaluateOnNewDocument(cmd: anytype) !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;
|
||||||
@@ -201,7 +198,7 @@ fn removeScriptToEvaluateOnNewDocument(cmd: *CDP.Command) !void {
|
|||||||
return cmd.sendResult(null, .{});
|
return cmd.sendResult(null, .{});
|
||||||
}
|
}
|
||||||
|
|
||||||
fn close(cmd: *CDP.Command) !void {
|
fn close(cmd: anytype) !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;
|
||||||
@@ -238,7 +235,7 @@ fn close(cmd: *CDP.Command) !void {
|
|||||||
bc.target_id = null;
|
bc.target_id = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn createIsolatedWorld(cmd: *CDP.Command) !void {
|
fn createIsolatedWorld(cmd: anytype) !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,
|
||||||
@@ -258,7 +255,7 @@ fn createIsolatedWorld(cmd: *CDP.Command) !void {
|
|||||||
return cmd.sendResult(.{ .executionContextId = js_context.id }, .{});
|
return cmd.sendResult(.{ .executionContextId = js_context.id }, .{});
|
||||||
}
|
}
|
||||||
|
|
||||||
fn navigate(cmd: *CDP.Command) !void {
|
fn navigate(cmd: anytype) !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,
|
||||||
@@ -292,7 +289,7 @@ fn navigate(cmd: *CDP.Command) !void {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
fn doReload(cmd: *CDP.Command) !void {
|
fn doReload(cmd: anytype) !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,
|
||||||
@@ -322,7 +319,7 @@ fn doReload(cmd: *CDP.Command) !void {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn pageNavigate(bc: *CDP.BrowserContext, event: *const Notification.PageNavigate) !void {
|
pub fn pageNavigate(bc: anytype, 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;
|
||||||
@@ -374,7 +371,7 @@ pub fn pageNavigate(bc: *CDP.BrowserContext, event: *const Notification.PageNavi
|
|||||||
}, .{ .session_id = session_id });
|
}, .{ .session_id = session_id });
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn pageRemove(bc: *CDP.BrowserContext) !void {
|
pub fn pageRemove(bc: anytype) !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();
|
||||||
@@ -385,7 +382,7 @@ pub fn pageRemove(bc: *CDP.BrowserContext) !void {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn pageCreated(bc: *CDP.BrowserContext, page: *Page) !void {
|
pub fn pageCreated(bc: anytype, 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| {
|
||||||
@@ -397,7 +394,7 @@ pub fn pageCreated(bc: *CDP.BrowserContext, page: *Page) !void {
|
|||||||
bc.captured_responses = .empty;
|
bc.captured_responses = .empty;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn pageFrameCreated(bc: *CDP.BrowserContext, event: *const Notification.PageFrameCreated) !void {
|
pub fn pageFrameCreated(bc: anytype, 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;
|
||||||
@@ -418,7 +415,7 @@ pub fn pageFrameCreated(bc: *CDP.BrowserContext, event: *const Notification.Page
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn pageNavigated(arena: Allocator, bc: *CDP.BrowserContext, event: *const Notification.PageNavigated) !void {
|
pub fn pageNavigated(arena: Allocator, bc: anytype, 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;
|
||||||
@@ -600,15 +597,15 @@ pub fn pageNavigated(arena: Allocator, bc: *CDP.BrowserContext, event: *const No
|
|||||||
}, .{ .session_id = session_id });
|
}, .{ .session_id = session_id });
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn pageNetworkIdle(bc: *CDP.BrowserContext, event: *const Notification.PageNetworkIdle) !void {
|
pub fn pageNetworkIdle(bc: anytype, 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: *CDP.BrowserContext, event: *const Notification.PageNetworkAlmostIdle) !void {
|
pub fn pageNetworkAlmostIdle(bc: anytype, 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: *CDP.BrowserContext, name: []const u8, timestamp: u64, frame_id: []const u8, loader_id: []const u8) !void {
|
fn sendPageLifecycle(bc: anytype, 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;
|
||||||
@@ -643,7 +640,7 @@ fn base64Encode(comptime input: []const u8) [std.base64.standard.Encoder.calcSiz
|
|||||||
return buf;
|
return buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn captureScreenshot(cmd: *CDP.Command) !void {
|
fn captureScreenshot(cmd: anytype) !void {
|
||||||
const Params = struct {
|
const Params = struct {
|
||||||
format: ?[]const u8 = "png",
|
format: ?[]const u8 = "png",
|
||||||
quality: ?u8 = null,
|
quality: ?u8 = null,
|
||||||
@@ -679,7 +676,7 @@ fn captureScreenshot(cmd: *CDP.Command) !void {
|
|||||||
}, .{});
|
}, .{});
|
||||||
}
|
}
|
||||||
|
|
||||||
fn getLayoutMetrics(cmd: *CDP.Command) !void {
|
fn getLayoutMetrics(cmd: anytype) !void {
|
||||||
const width = 1920;
|
const width = 1920;
|
||||||
const height = 1080;
|
const height = 1080;
|
||||||
|
|
||||||
|
|||||||
@@ -17,9 +17,8 @@
|
|||||||
// 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: *CDP.Command) !void {
|
pub fn processMessage(cmd: anytype) !void {
|
||||||
const action = std.meta.stringToEnum(enum {
|
const action = std.meta.stringToEnum(enum {
|
||||||
enable,
|
enable,
|
||||||
disable,
|
disable,
|
||||||
|
|||||||
@@ -19,9 +19,7 @@
|
|||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
const builtin = @import("builtin");
|
const builtin = @import("builtin");
|
||||||
|
|
||||||
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,
|
||||||
runIfWaitingForDebugger,
|
runIfWaitingForDebugger,
|
||||||
@@ -38,7 +36,7 @@ pub fn processMessage(cmd: *CDP.Command) !void {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn sendInspector(cmd: *CDP.Command, action: anytype) !void {
|
fn sendInspector(cmd: anytype, 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);
|
||||||
@@ -50,7 +48,7 @@ fn sendInspector(cmd: *CDP.Command, action: anytype) !void {
|
|||||||
bc.callInspector(cmd.input.json);
|
bc.callInspector(cmd.input.json);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn logInspector(cmd: *CDP.Command, action: anytype) !void {
|
fn logInspector(cmd: anytype, 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,9 +17,8 @@
|
|||||||
// 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: *CDP.Command) !void {
|
pub fn processMessage(cmd: anytype) !void {
|
||||||
const action = std.meta.stringToEnum(enum {
|
const action = std.meta.stringToEnum(enum {
|
||||||
enable,
|
enable,
|
||||||
disable,
|
disable,
|
||||||
@@ -33,7 +32,7 @@ pub fn processMessage(cmd: *CDP.Command) !void {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn setIgnoreCertificateErrors(cmd: *CDP.Command) !void {
|
fn setIgnoreCertificateErrors(cmd: anytype) !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,16 +18,13 @@
|
|||||||
|
|
||||||
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: *CDP.Command) !void {
|
pub fn processMessage(cmd: anytype) !void {
|
||||||
const action = std.meta.stringToEnum(enum {
|
const action = std.meta.stringToEnum(enum {
|
||||||
clearCookies,
|
clearCookies,
|
||||||
setCookies,
|
setCookies,
|
||||||
@@ -43,7 +40,7 @@ pub fn processMessage(cmd: *CDP.Command) !void {
|
|||||||
|
|
||||||
const BrowserContextParam = struct { browserContextId: ?[]const u8 = null };
|
const BrowserContextParam = struct { browserContextId: ?[]const u8 = null };
|
||||||
|
|
||||||
fn clearCookies(cmd: *CDP.Command) !void {
|
fn clearCookies(cmd: anytype) !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{};
|
||||||
|
|
||||||
@@ -58,7 +55,7 @@ fn clearCookies(cmd: *CDP.Command) !void {
|
|||||||
return cmd.sendResult(null, .{});
|
return cmd.sendResult(null, .{});
|
||||||
}
|
}
|
||||||
|
|
||||||
fn getCookies(cmd: *CDP.Command) !void {
|
fn getCookies(cmd: anytype) !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{};
|
||||||
|
|
||||||
@@ -72,7 +69,7 @@ fn getCookies(cmd: *CDP.Command) !void {
|
|||||||
try cmd.sendResult(.{ .cookies = writer }, .{});
|
try cmd.sendResult(.{ .cookies = writer }, .{});
|
||||||
}
|
}
|
||||||
|
|
||||||
fn setCookies(cmd: *CDP.Command) !void {
|
fn setCookies(cmd: anytype) !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,13 +20,11 @@ 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: *CDP.Command) !void {
|
pub fn processMessage(cmd: anytype) !void {
|
||||||
const action = std.meta.stringToEnum(enum {
|
const action = std.meta.stringToEnum(enum {
|
||||||
getTargets,
|
getTargets,
|
||||||
attachToTarget,
|
attachToTarget,
|
||||||
@@ -62,7 +60,7 @@ pub fn processMessage(cmd: *CDP.Command) !void {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn getTargets(cmd: *CDP.Command) !void {
|
fn getTargets(cmd: anytype) !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(.{
|
||||||
@@ -88,7 +86,7 @@ fn getTargets(cmd: *CDP.Command) !void {
|
|||||||
}, .{ .include_session_id = false });
|
}, .{ .include_session_id = false });
|
||||||
}
|
}
|
||||||
|
|
||||||
fn getBrowserContexts(cmd: *CDP.Command) !void {
|
fn getBrowserContexts(cmd: anytype) !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};
|
||||||
@@ -101,7 +99,7 @@ fn getBrowserContexts(cmd: *CDP.Command) !void {
|
|||||||
}, .{ .include_session_id = false });
|
}, .{ .include_session_id = false });
|
||||||
}
|
}
|
||||||
|
|
||||||
fn createBrowserContext(cmd: *CDP.Command) !void {
|
fn createBrowserContext(cmd: anytype) !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,
|
||||||
@@ -132,7 +130,7 @@ fn createBrowserContext(cmd: *CDP.Command) !void {
|
|||||||
}, .{});
|
}, .{});
|
||||||
}
|
}
|
||||||
|
|
||||||
fn disposeBrowserContext(cmd: *CDP.Command) !void {
|
fn disposeBrowserContext(cmd: anytype) !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;
|
||||||
@@ -143,7 +141,7 @@ fn disposeBrowserContext(cmd: *CDP.Command) !void {
|
|||||||
try cmd.sendResult(null, .{});
|
try cmd.sendResult(null, .{});
|
||||||
}
|
}
|
||||||
|
|
||||||
fn createTarget(cmd: *CDP.Command) !void {
|
fn createTarget(cmd: anytype) !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,
|
||||||
@@ -232,7 +230,7 @@ fn createTarget(cmd: *CDP.Command) !void {
|
|||||||
}, .{});
|
}, .{});
|
||||||
}
|
}
|
||||||
|
|
||||||
fn attachToTarget(cmd: *CDP.Command) !void {
|
fn attachToTarget(cmd: anytype) !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,
|
||||||
@@ -249,7 +247,7 @@ fn attachToTarget(cmd: *CDP.Command) !void {
|
|||||||
return cmd.sendResult(.{ .sessionId = bc.session_id }, .{});
|
return cmd.sendResult(.{ .sessionId = bc.session_id }, .{});
|
||||||
}
|
}
|
||||||
|
|
||||||
fn attachToBrowserTarget(cmd: *CDP.Command) !void {
|
fn attachToBrowserTarget(cmd: anytype) !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();
|
||||||
@@ -271,7 +269,7 @@ fn attachToBrowserTarget(cmd: *CDP.Command) !void {
|
|||||||
return cmd.sendResult(.{ .sessionId = bc.session_id }, .{});
|
return cmd.sendResult(.{ .sessionId = bc.session_id }, .{});
|
||||||
}
|
}
|
||||||
|
|
||||||
fn closeTarget(cmd: *CDP.Command) !void {
|
fn closeTarget(cmd: anytype) !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;
|
||||||
@@ -312,7 +310,7 @@ fn closeTarget(cmd: *CDP.Command) !void {
|
|||||||
bc.target_id = null;
|
bc.target_id = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn getTargetInfo(cmd: *CDP.Command) !void {
|
fn getTargetInfo(cmd: anytype) !void {
|
||||||
const Params = struct {
|
const Params = struct {
|
||||||
targetId: ?[]const u8 = null,
|
targetId: ?[]const u8 = null,
|
||||||
};
|
};
|
||||||
@@ -349,7 +347,7 @@ fn getTargetInfo(cmd: *CDP.Command) !void {
|
|||||||
}, .{ .include_session_id = false });
|
}, .{ .include_session_id = false });
|
||||||
}
|
}
|
||||||
|
|
||||||
fn sendMessageToTarget(cmd: *CDP.Command) !void {
|
fn sendMessageToTarget(cmd: anytype) !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,
|
||||||
@@ -367,19 +365,32 @@ fn sendMessageToTarget(cmd: *CDP.Command) !void {
|
|||||||
return error.UnknownSessionId;
|
return error.UnknownSessionId;
|
||||||
}
|
}
|
||||||
|
|
||||||
var aw = std.Io.Writer.Allocating.init(cmd.arena);
|
const Capture = struct {
|
||||||
cmd.cdp.dispatch(cmd.arena, .{ .capture = &aw.writer }, params.message) catch |err| {
|
aw: std.Io.Writer.Allocating,
|
||||||
|
|
||||||
|
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 = aw.written(),
|
.message = capture.aw.written(),
|
||||||
.sessionId = params.sessionId,
|
.sessionId = params.sessionId,
|
||||||
}, .{});
|
}, .{});
|
||||||
}
|
}
|
||||||
|
|
||||||
fn detachFromTarget(cmd: *CDP.Command) !void {
|
fn detachFromTarget(cmd: anytype) !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", .{
|
||||||
@@ -393,11 +404,11 @@ fn detachFromTarget(cmd: *CDP.Command) !void {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// TODO: noop method
|
// TODO: noop method
|
||||||
fn setDiscoverTargets(cmd: *CDP.Command) !void {
|
fn setDiscoverTargets(cmd: anytype) !void {
|
||||||
return cmd.sendResult(null, .{});
|
return cmd.sendResult(null, .{});
|
||||||
}
|
}
|
||||||
|
|
||||||
fn setAutoAttach(cmd: *CDP.Command) !void {
|
fn setAutoAttach(cmd: anytype) !void {
|
||||||
const params = (try cmd.params(struct {
|
const params = (try cmd.params(struct {
|
||||||
autoAttach: bool,
|
autoAttach: bool,
|
||||||
waitForDebuggerOnStart: bool,
|
waitForDebuggerOnStart: bool,
|
||||||
@@ -457,7 +468,7 @@ fn setAutoAttach(cmd: *CDP.Command) !void {
|
|||||||
try cmd.sendResult(null, .{});
|
try cmd.sendResult(null, .{});
|
||||||
}
|
}
|
||||||
|
|
||||||
fn doAttachtoTarget(cmd: *CDP.Command, target_id: []const u8) !void {
|
fn doAttachtoTarget(cmd: anytype, 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 {
|
pub fn loadBrowserContext(self: *TestContext, opts: BrowserContextOpts) !*CDP.BrowserContext(CDP) {
|
||||||
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);
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
|
|
||||||
pub const protocol = @import("mcp/protocol.zig");
|
pub const protocol = @import("mcp/protocol.zig");
|
||||||
|
pub const Version = protocol.Version;
|
||||||
pub const router = @import("mcp/router.zig");
|
pub const router = @import("mcp/router.zig");
|
||||||
pub const Server = @import("mcp/Server.zig");
|
pub const Server = @import("mcp/Server.zig");
|
||||||
|
|
||||||
|
|||||||
@@ -114,7 +114,7 @@ test "MCP.Server - Integration: synchronous smoke test" {
|
|||||||
|
|
||||||
try router.processRequests(server, &in_reader);
|
try router.processRequests(server, &in_reader);
|
||||||
|
|
||||||
try testing.expectJson(.{ .jsonrpc = "2.0", .id = 1 }, out_alloc.writer.buffered());
|
try testing.expectJson(.{ .jsonrpc = "2.0", .id = 1, .result = .{ .protocolVersion = "2024-11-05" } }, out_alloc.writer.buffered());
|
||||||
}
|
}
|
||||||
|
|
||||||
test "MCP.Server - Integration: ping request returns an empty result" {
|
test "MCP.Server - Integration: ping request returns an empty result" {
|
||||||
|
|||||||
@@ -1,5 +1,14 @@
|
|||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
|
|
||||||
|
pub const Version = enum {
|
||||||
|
@"2024-11-05",
|
||||||
|
@"2025-03-26",
|
||||||
|
@"2025-06-18",
|
||||||
|
@"2025-11-25",
|
||||||
|
|
||||||
|
pub const default: Version = .@"2024-11-05";
|
||||||
|
};
|
||||||
|
|
||||||
pub const Request = struct {
|
pub const Request = struct {
|
||||||
jsonrpc: []const u8 = "2.0",
|
jsonrpc: []const u8 = "2.0",
|
||||||
id: ?std.json.Value = null,
|
id: ?std.json.Value = null,
|
||||||
|
|||||||
@@ -81,8 +81,12 @@ pub fn handleMessage(server: *Server, arena: std.mem.Allocator, msg: []const u8)
|
|||||||
|
|
||||||
fn handleInitialize(server: *Server, req: protocol.Request) !void {
|
fn handleInitialize(server: *Server, req: protocol.Request) !void {
|
||||||
const id = req.id orelse return;
|
const id = req.id orelse return;
|
||||||
const result = protocol.InitializeResult{
|
const version: protocol.Version = switch (server.app.config.mode) {
|
||||||
.protocolVersion = "2025-11-25",
|
.mcp => |opts| opts.version,
|
||||||
|
else => .default,
|
||||||
|
};
|
||||||
|
const result: protocol.InitializeResult = .{
|
||||||
|
.protocolVersion = @tagName(version),
|
||||||
.capabilities = .{
|
.capabilities = .{
|
||||||
.resources = .{},
|
.resources = .{},
|
||||||
.tools = .{},
|
.tools = .{},
|
||||||
@@ -121,7 +125,7 @@ test "MCP.router - handleMessage - synchronous unit tests" {
|
|||||||
\\{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2024-11-05","capabilities":{},"clientInfo":{"name":"test-client","version":"1.0.0"}}}
|
\\{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2024-11-05","capabilities":{},"clientInfo":{"name":"test-client","version":"1.0.0"}}}
|
||||||
);
|
);
|
||||||
try testing.expectJson(
|
try testing.expectJson(
|
||||||
\\{ "jsonrpc": "2.0", "id": 1, "result": { "capabilities": { "tools": {} } } }
|
\\{ "jsonrpc": "2.0", "id": 1, "result": { "protocolVersion": "2024-11-05", "capabilities": { "tools": {} } } }
|
||||||
, out_alloc.writer.buffered());
|
, out_alloc.writer.buffered());
|
||||||
out_alloc.writer.end = 0;
|
out_alloc.writer.end = 0;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user