mirror of
https://github.com/lightpanda-io/browser.git
synced 2025-10-29 15:13:28 +00:00
cdp: refacto message JSON read
This commit is contained in:
@@ -22,7 +22,7 @@ const server = @import("../server.zig");
|
|||||||
const Ctx = server.Ctx;
|
const Ctx = server.Ctx;
|
||||||
const cdp = @import("cdp.zig");
|
const cdp = @import("cdp.zig");
|
||||||
const result = cdp.result;
|
const result = cdp.result;
|
||||||
const getMsg = cdp.getMsg;
|
const IncomingMessage = @import("msg.zig").IncomingMessage;
|
||||||
|
|
||||||
const log = std.log.scoped(.cdp);
|
const log = std.log.scoped(.cdp);
|
||||||
|
|
||||||
@@ -35,18 +35,17 @@ const Methods = enum {
|
|||||||
|
|
||||||
pub fn browser(
|
pub fn browser(
|
||||||
alloc: std.mem.Allocator,
|
alloc: std.mem.Allocator,
|
||||||
id: ?u16,
|
msg: *IncomingMessage,
|
||||||
action: []const u8,
|
action: []const u8,
|
||||||
scanner: *std.json.Scanner,
|
|
||||||
ctx: *Ctx,
|
ctx: *Ctx,
|
||||||
) ![]const u8 {
|
) ![]const u8 {
|
||||||
const method = std.meta.stringToEnum(Methods, action) orelse
|
const method = std.meta.stringToEnum(Methods, action) orelse
|
||||||
return error.UnknownMethod;
|
return error.UnknownMethod;
|
||||||
return switch (method) {
|
return switch (method) {
|
||||||
.getVersion => getVersion(alloc, id, scanner, ctx),
|
.getVersion => getVersion(alloc, msg, ctx),
|
||||||
.setDownloadBehavior => setDownloadBehavior(alloc, id, scanner, ctx),
|
.setDownloadBehavior => setDownloadBehavior(alloc, msg, ctx),
|
||||||
.getWindowForTarget => getWindowForTarget(alloc, id, scanner, ctx),
|
.getWindowForTarget => getWindowForTarget(alloc, msg, ctx),
|
||||||
.setWindowBounds => setWindowBounds(alloc, id, scanner, ctx),
|
.setWindowBounds => setWindowBounds(alloc, msg, ctx),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -59,14 +58,12 @@ const JsVersion = "12.4.254.8";
|
|||||||
|
|
||||||
fn getVersion(
|
fn getVersion(
|
||||||
alloc: std.mem.Allocator,
|
alloc: std.mem.Allocator,
|
||||||
_id: ?u16,
|
msg: *IncomingMessage,
|
||||||
scanner: *std.json.Scanner,
|
|
||||||
_: *Ctx,
|
_: *Ctx,
|
||||||
) ![]const u8 {
|
) ![]const u8 {
|
||||||
|
|
||||||
// input
|
// input
|
||||||
const msg = try getMsg(alloc, _id, void, scanner);
|
const input = try msg.getInput(alloc, void);
|
||||||
log.debug("Req > id {d}, method {s}", .{ msg.id, "browser.getVersion" });
|
log.debug("Req > id {d}, method {s}", .{ input.id, "browser.getVersion" });
|
||||||
|
|
||||||
// ouput
|
// ouput
|
||||||
const Res = struct {
|
const Res = struct {
|
||||||
@@ -76,17 +73,15 @@ fn getVersion(
|
|||||||
userAgent: []const u8 = UserAgent,
|
userAgent: []const u8 = UserAgent,
|
||||||
jsVersion: []const u8 = JsVersion,
|
jsVersion: []const u8 = JsVersion,
|
||||||
};
|
};
|
||||||
return result(alloc, msg.id, Res, .{}, null);
|
return result(alloc, input.id, Res, .{}, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: noop method
|
// TODO: noop method
|
||||||
fn setDownloadBehavior(
|
fn setDownloadBehavior(
|
||||||
alloc: std.mem.Allocator,
|
alloc: std.mem.Allocator,
|
||||||
_id: ?u16,
|
msg: *IncomingMessage,
|
||||||
scanner: *std.json.Scanner,
|
|
||||||
_: *Ctx,
|
_: *Ctx,
|
||||||
) ![]const u8 {
|
) ![]const u8 {
|
||||||
|
|
||||||
// input
|
// input
|
||||||
const Params = struct {
|
const Params = struct {
|
||||||
behavior: []const u8,
|
behavior: []const u8,
|
||||||
@@ -94,11 +89,11 @@ fn setDownloadBehavior(
|
|||||||
downloadPath: ?[]const u8 = null,
|
downloadPath: ?[]const u8 = null,
|
||||||
eventsEnabled: ?bool = null,
|
eventsEnabled: ?bool = null,
|
||||||
};
|
};
|
||||||
const msg = try getMsg(alloc, _id, Params, scanner);
|
const input = try msg.getInput(alloc, Params);
|
||||||
log.debug("REQ > id {d}, method {s}", .{ msg.id, "browser.setDownloadBehavior" });
|
log.debug("REQ > id {d}, method {s}", .{ input.id, "browser.setDownloadBehavior" });
|
||||||
|
|
||||||
// output
|
// output
|
||||||
return result(alloc, msg.id, null, null, null);
|
return result(alloc, input.id, null, null, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: hard coded ID
|
// TODO: hard coded ID
|
||||||
@@ -106,8 +101,7 @@ const DevToolsWindowID = 1923710101;
|
|||||||
|
|
||||||
fn getWindowForTarget(
|
fn getWindowForTarget(
|
||||||
alloc: std.mem.Allocator,
|
alloc: std.mem.Allocator,
|
||||||
_id: ?u16,
|
msg: *IncomingMessage,
|
||||||
scanner: *std.json.Scanner,
|
|
||||||
_: *Ctx,
|
_: *Ctx,
|
||||||
) ![]const u8 {
|
) ![]const u8 {
|
||||||
|
|
||||||
@@ -115,9 +109,9 @@ fn getWindowForTarget(
|
|||||||
const Params = struct {
|
const Params = struct {
|
||||||
targetId: ?[]const u8 = null,
|
targetId: ?[]const u8 = null,
|
||||||
};
|
};
|
||||||
const msg = try cdp.getMsg(alloc, _id, ?Params, scanner);
|
const input = try msg.getInput(alloc, Params);
|
||||||
std.debug.assert(msg.sessionID != null);
|
std.debug.assert(input.sessionId != null);
|
||||||
log.debug("Req > id {d}, method {s}", .{ msg.id, "browser.getWindowForTarget" });
|
log.debug("Req > id {d}, method {s}", .{ input.id, "browser.getWindowForTarget" });
|
||||||
|
|
||||||
// output
|
// output
|
||||||
const Resp = struct {
|
const Resp = struct {
|
||||||
@@ -130,21 +124,20 @@ fn getWindowForTarget(
|
|||||||
windowState: []const u8 = "normal",
|
windowState: []const u8 = "normal",
|
||||||
} = .{},
|
} = .{},
|
||||||
};
|
};
|
||||||
return result(alloc, msg.id, Resp, Resp{}, msg.sessionID.?);
|
return result(alloc, input.id, Resp, Resp{}, input.sessionId);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: noop method
|
// TODO: noop method
|
||||||
fn setWindowBounds(
|
fn setWindowBounds(
|
||||||
alloc: std.mem.Allocator,
|
alloc: std.mem.Allocator,
|
||||||
_id: ?u16,
|
msg: *IncomingMessage,
|
||||||
scanner: *std.json.Scanner,
|
|
||||||
_: *Ctx,
|
_: *Ctx,
|
||||||
) ![]const u8 {
|
) ![]const u8 {
|
||||||
|
const input = try msg.getInput(alloc, void);
|
||||||
|
|
||||||
// input
|
// input
|
||||||
const msg = try cdp.getMsg(alloc, _id, void, scanner);
|
log.debug("Req > id {d}, method {s}", .{ input.id, "browser.setWindowBounds" });
|
||||||
log.debug("Req > id {d}, method {s}", .{ msg.id, "browser.setWindowBounds" });
|
|
||||||
|
|
||||||
// output
|
// output
|
||||||
return result(alloc, msg.id, null, null, msg.sessionID);
|
return result(alloc, input.id, null, null, input.sessionId);
|
||||||
}
|
}
|
||||||
|
|||||||
154
src/cdp/cdp.zig
154
src/cdp/cdp.zig
@@ -30,6 +30,7 @@ const network = @import("network.zig").network;
|
|||||||
const emulation = @import("emulation.zig").emulation;
|
const emulation = @import("emulation.zig").emulation;
|
||||||
const fetch = @import("fetch.zig").fetch;
|
const fetch = @import("fetch.zig").fetch;
|
||||||
const performance = @import("performance.zig").performance;
|
const performance = @import("performance.zig").performance;
|
||||||
|
const IncomingMessage = @import("msg.zig").IncomingMessage;
|
||||||
|
|
||||||
const log_cdp = std.log.scoped(.cdp);
|
const log_cdp = std.log.scoped(.cdp);
|
||||||
|
|
||||||
@@ -70,51 +71,29 @@ pub fn do(
|
|||||||
ctx: *Ctx,
|
ctx: *Ctx,
|
||||||
) ![]const u8 {
|
) ![]const u8 {
|
||||||
|
|
||||||
// JSON scanner
|
// incoming message parser
|
||||||
var scanner = std.json.Scanner.initCompleteInput(alloc, s);
|
var msg = IncomingMessage.init(alloc, s);
|
||||||
defer scanner.deinit();
|
defer msg.deinit();
|
||||||
|
|
||||||
std.debug.assert(try scanner.next() == .object_begin);
|
const method = try msg.getMethod();
|
||||||
|
|
||||||
// handle 2 possible orders:
|
|
||||||
// - id, method <...>
|
|
||||||
// - method, id <...>
|
|
||||||
var method_key = try nextString(&scanner);
|
|
||||||
var method_token: std.json.Token = undefined;
|
|
||||||
var id: ?u16 = null;
|
|
||||||
// check swap order
|
|
||||||
if (std.mem.eql(u8, method_key, "id")) {
|
|
||||||
id = try getId(&scanner, method_key);
|
|
||||||
method_key = try nextString(&scanner);
|
|
||||||
method_token = try scanner.next();
|
|
||||||
} else {
|
|
||||||
method_token = try scanner.next();
|
|
||||||
}
|
|
||||||
try checkKey(method_key, "method");
|
|
||||||
|
|
||||||
// retrieve method
|
|
||||||
if (method_token != .string) {
|
|
||||||
return error.WrongTokenType;
|
|
||||||
}
|
|
||||||
const method_name = method_token.string;
|
|
||||||
|
|
||||||
// retrieve domain from method
|
// retrieve domain from method
|
||||||
var iter = std.mem.splitScalar(u8, method_name, '.');
|
var iter = std.mem.splitScalar(u8, method, '.');
|
||||||
const domain = std.meta.stringToEnum(Domains, iter.first()) orelse
|
const domain = std.meta.stringToEnum(Domains, iter.first()) orelse
|
||||||
return error.UnknonwDomain;
|
return error.UnknonwDomain;
|
||||||
|
|
||||||
// select corresponding domain
|
// select corresponding domain
|
||||||
const action = iter.next() orelse return error.BadMethod;
|
const action = iter.next() orelse return error.BadMethod;
|
||||||
return switch (domain) {
|
return switch (domain) {
|
||||||
.Browser => browser(alloc, id, action, &scanner, ctx),
|
.Browser => browser(alloc, &msg, action, ctx),
|
||||||
.Target => target(alloc, id, action, &scanner, ctx),
|
.Target => target(alloc, &msg, action, ctx),
|
||||||
.Page => page(alloc, id, action, &scanner, ctx),
|
.Page => page(alloc, &msg, action, ctx),
|
||||||
.Log => log(alloc, id, action, &scanner, ctx),
|
.Log => log(alloc, &msg, action, ctx),
|
||||||
.Runtime => runtime(alloc, id, action, &scanner, s, ctx),
|
.Runtime => runtime(alloc, &msg, action, ctx),
|
||||||
.Network => network(alloc, id, action, &scanner, ctx),
|
.Network => network(alloc, &msg, action, ctx),
|
||||||
.Emulation => emulation(alloc, id, action, &scanner, ctx),
|
.Emulation => emulation(alloc, &msg, action, ctx),
|
||||||
.Fetch => fetch(alloc, id, action, &scanner, ctx),
|
.Fetch => fetch(alloc, &msg, action, ctx),
|
||||||
.Performance => performance(alloc, id, action, &scanner, ctx),
|
.Performance => performance(alloc, &msg, action, ctx),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -133,14 +112,6 @@ pub const State = struct {
|
|||||||
// Utils
|
// Utils
|
||||||
// -----
|
// -----
|
||||||
|
|
||||||
fn nextString(scanner: *std.json.Scanner) ![]const u8 {
|
|
||||||
const token = try scanner.next();
|
|
||||||
if (token != .string) {
|
|
||||||
return error.WrongTokenType;
|
|
||||||
}
|
|
||||||
return token.string;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn dumpFile(
|
pub fn dumpFile(
|
||||||
alloc: std.mem.Allocator,
|
alloc: std.mem.Allocator,
|
||||||
id: u16,
|
id: u16,
|
||||||
@@ -158,10 +129,6 @@ pub fn dumpFile(
|
|||||||
defer alloc.free(p);
|
defer alloc.free(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn checkKey(key: []const u8, token: []const u8) !void {
|
|
||||||
if (!std.mem.eql(u8, key, token)) return error.WrongToken;
|
|
||||||
}
|
|
||||||
|
|
||||||
// caller owns the slice returned
|
// caller owns the slice returned
|
||||||
pub fn stringify(alloc: std.mem.Allocator, res: anytype) ![]const u8 {
|
pub fn stringify(alloc: std.mem.Allocator, res: anytype) ![]const u8 {
|
||||||
var out = std.ArrayList(u8).init(alloc);
|
var out = std.ArrayList(u8).init(alloc);
|
||||||
@@ -229,97 +196,6 @@ pub fn sendEvent(
|
|||||||
try server.sendAsync(ctx, event_msg);
|
try server.sendAsync(ctx, event_msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn getParams(
|
|
||||||
alloc: std.mem.Allocator,
|
|
||||||
comptime T: type,
|
|
||||||
scanner: *std.json.Scanner,
|
|
||||||
key: []const u8,
|
|
||||||
) !?T {
|
|
||||||
|
|
||||||
// check key is "params"
|
|
||||||
if (!std.mem.eql(u8, "params", key)) return null;
|
|
||||||
|
|
||||||
// skip "params" if not requested
|
|
||||||
if (T == void) {
|
|
||||||
var finished: usize = 0;
|
|
||||||
while (true) {
|
|
||||||
switch (try scanner.next()) {
|
|
||||||
.object_begin => finished += 1,
|
|
||||||
.object_end => finished -= 1,
|
|
||||||
else => continue,
|
|
||||||
}
|
|
||||||
if (finished == 0) break;
|
|
||||||
}
|
|
||||||
return void{};
|
|
||||||
}
|
|
||||||
|
|
||||||
// parse "params"
|
|
||||||
const options = std.json.ParseOptions{
|
|
||||||
.max_value_len = scanner.input.len,
|
|
||||||
.allocate = .alloc_if_needed,
|
|
||||||
};
|
|
||||||
return try std.json.innerParse(T, alloc, scanner, options);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn getId(scanner: *std.json.Scanner, key: []const u8) !?u16 {
|
|
||||||
|
|
||||||
// check key is "id"
|
|
||||||
if (!std.mem.eql(u8, "id", key)) return null;
|
|
||||||
|
|
||||||
// parse "id"
|
|
||||||
return try std.fmt.parseUnsigned(u16, (try scanner.next()).number, 10);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn getSessionId(scanner: *std.json.Scanner, key: []const u8) !?[]const u8 {
|
|
||||||
|
|
||||||
// check key is "sessionId"
|
|
||||||
if (!std.mem.eql(u8, "sessionId", key)) return null;
|
|
||||||
|
|
||||||
// parse "sessionId"
|
|
||||||
return try nextString(scanner);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn getMsg(
|
|
||||||
alloc: std.mem.Allocator,
|
|
||||||
_id: ?u16,
|
|
||||||
comptime params_T: type,
|
|
||||||
scanner: *std.json.Scanner,
|
|
||||||
) !struct { id: u16, params: ?params_T, sessionID: ?[]const u8 } {
|
|
||||||
var id_msg: ?u16 = null;
|
|
||||||
var params: ?params_T = null;
|
|
||||||
var sessionID: ?[]const u8 = null;
|
|
||||||
|
|
||||||
var t: std.json.Token = undefined;
|
|
||||||
|
|
||||||
while (true) {
|
|
||||||
t = try scanner.next();
|
|
||||||
if (t == .object_end) break;
|
|
||||||
if (t != .string) {
|
|
||||||
return error.WrongTokenType;
|
|
||||||
}
|
|
||||||
if (_id == null and id_msg == null) {
|
|
||||||
id_msg = try getId(scanner, t.string);
|
|
||||||
if (id_msg != null) continue;
|
|
||||||
}
|
|
||||||
if (params == null) {
|
|
||||||
params = try getParams(alloc, params_T, scanner, t.string);
|
|
||||||
if (params != null) continue;
|
|
||||||
}
|
|
||||||
if (sessionID == null) {
|
|
||||||
sessionID = try getSessionId(scanner, t.string);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// end
|
|
||||||
t = try scanner.next();
|
|
||||||
if (t != .end_of_document) return error.CDPMsgEnd;
|
|
||||||
|
|
||||||
// check id
|
|
||||||
if (_id == null and id_msg == null) return error.RequestWithoutID;
|
|
||||||
|
|
||||||
return .{ .id = _id orelse id_msg.?, .params = params, .sessionID = sessionID };
|
|
||||||
}
|
|
||||||
|
|
||||||
// Common
|
// Common
|
||||||
// ------
|
// ------
|
||||||
|
|
||||||
|
|||||||
@@ -22,8 +22,8 @@ const server = @import("../server.zig");
|
|||||||
const Ctx = server.Ctx;
|
const Ctx = server.Ctx;
|
||||||
const cdp = @import("cdp.zig");
|
const cdp = @import("cdp.zig");
|
||||||
const result = cdp.result;
|
const result = cdp.result;
|
||||||
const getMsg = cdp.getMsg;
|
|
||||||
const stringify = cdp.stringify;
|
const stringify = cdp.stringify;
|
||||||
|
const IncomingMessage = @import("msg.zig").IncomingMessage;
|
||||||
|
|
||||||
const log = std.log.scoped(.cdp);
|
const log = std.log.scoped(.cdp);
|
||||||
|
|
||||||
@@ -36,18 +36,17 @@ const Methods = enum {
|
|||||||
|
|
||||||
pub fn emulation(
|
pub fn emulation(
|
||||||
alloc: std.mem.Allocator,
|
alloc: std.mem.Allocator,
|
||||||
id: ?u16,
|
msg: *IncomingMessage,
|
||||||
action: []const u8,
|
action: []const u8,
|
||||||
scanner: *std.json.Scanner,
|
|
||||||
ctx: *Ctx,
|
ctx: *Ctx,
|
||||||
) ![]const u8 {
|
) ![]const u8 {
|
||||||
const method = std.meta.stringToEnum(Methods, action) orelse
|
const method = std.meta.stringToEnum(Methods, action) orelse
|
||||||
return error.UnknownMethod;
|
return error.UnknownMethod;
|
||||||
return switch (method) {
|
return switch (method) {
|
||||||
.setEmulatedMedia => setEmulatedMedia(alloc, id, scanner, ctx),
|
.setEmulatedMedia => setEmulatedMedia(alloc, msg, ctx),
|
||||||
.setFocusEmulationEnabled => setFocusEmulationEnabled(alloc, id, scanner, ctx),
|
.setFocusEmulationEnabled => setFocusEmulationEnabled(alloc, msg, ctx),
|
||||||
.setDeviceMetricsOverride => setDeviceMetricsOverride(alloc, id, scanner, ctx),
|
.setDeviceMetricsOverride => setDeviceMetricsOverride(alloc, msg, ctx),
|
||||||
.setTouchEmulationEnabled => setTouchEmulationEnabled(alloc, id, scanner, ctx),
|
.setTouchEmulationEnabled => setTouchEmulationEnabled(alloc, msg, ctx),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -59,8 +58,7 @@ const MediaFeature = struct {
|
|||||||
// TODO: noop method
|
// TODO: noop method
|
||||||
fn setEmulatedMedia(
|
fn setEmulatedMedia(
|
||||||
alloc: std.mem.Allocator,
|
alloc: std.mem.Allocator,
|
||||||
_id: ?u16,
|
msg: *IncomingMessage,
|
||||||
scanner: *std.json.Scanner,
|
|
||||||
_: *Ctx,
|
_: *Ctx,
|
||||||
) ![]const u8 {
|
) ![]const u8 {
|
||||||
|
|
||||||
@@ -69,57 +67,52 @@ fn setEmulatedMedia(
|
|||||||
media: ?[]const u8 = null,
|
media: ?[]const u8 = null,
|
||||||
features: ?[]MediaFeature = null,
|
features: ?[]MediaFeature = null,
|
||||||
};
|
};
|
||||||
const msg = try getMsg(alloc, _id, Params, scanner);
|
const input = try msg.getInput(alloc, Params);
|
||||||
log.debug("Req > id {d}, method {s}", .{ msg.id, "emulation.setEmulatedMedia" });
|
log.debug("Req > id {d}, method {s}", .{ input.id, "emulation.setEmulatedMedia" });
|
||||||
|
|
||||||
// output
|
// output
|
||||||
return result(alloc, msg.id, null, null, msg.sessionID);
|
return result(alloc, input.id, null, null, input.sessionId);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: noop method
|
// TODO: noop method
|
||||||
fn setFocusEmulationEnabled(
|
fn setFocusEmulationEnabled(
|
||||||
alloc: std.mem.Allocator,
|
alloc: std.mem.Allocator,
|
||||||
_id: ?u16,
|
msg: *IncomingMessage,
|
||||||
scanner: *std.json.Scanner,
|
|
||||||
_: *Ctx,
|
_: *Ctx,
|
||||||
) ![]const u8 {
|
) ![]const u8 {
|
||||||
|
|
||||||
// input
|
// input
|
||||||
const Params = struct {
|
const Params = struct {
|
||||||
enabled: bool,
|
enabled: bool,
|
||||||
};
|
};
|
||||||
const msg = try getMsg(alloc, _id, Params, scanner);
|
const input = try msg.getInput(alloc, Params);
|
||||||
log.debug("Req > id {d}, method {s}", .{ msg.id, "emulation.setFocusEmulationEnabled" });
|
log.debug("Req > id {d}, method {s}", .{ input.id, "emulation.setFocusEmulationEnabled" });
|
||||||
|
|
||||||
// output
|
// output
|
||||||
return result(alloc, msg.id, null, null, msg.sessionID);
|
return result(alloc, input.id, null, null, input.sessionId);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: noop method
|
// TODO: noop method
|
||||||
fn setDeviceMetricsOverride(
|
fn setDeviceMetricsOverride(
|
||||||
alloc: std.mem.Allocator,
|
alloc: std.mem.Allocator,
|
||||||
_id: ?u16,
|
msg: *IncomingMessage,
|
||||||
scanner: *std.json.Scanner,
|
|
||||||
_: *Ctx,
|
_: *Ctx,
|
||||||
) ![]const u8 {
|
) ![]const u8 {
|
||||||
|
|
||||||
// input
|
// input
|
||||||
const msg = try cdp.getMsg(alloc, _id, void, scanner);
|
const input = try msg.getInput(alloc, void);
|
||||||
log.debug("Req > id {d}, method {s}", .{ msg.id, "emulation.setDeviceMetricsOverride" });
|
log.debug("Req > id {d}, method {s}", .{ input.id, "emulation.setDeviceMetricsOverride" });
|
||||||
|
|
||||||
// output
|
// output
|
||||||
return result(alloc, msg.id, null, null, msg.sessionID);
|
return result(alloc, input.id, null, null, input.sessionId);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: noop method
|
// TODO: noop method
|
||||||
fn setTouchEmulationEnabled(
|
fn setTouchEmulationEnabled(
|
||||||
alloc: std.mem.Allocator,
|
alloc: std.mem.Allocator,
|
||||||
_id: ?u16,
|
msg: *IncomingMessage,
|
||||||
scanner: *std.json.Scanner,
|
|
||||||
_: *Ctx,
|
_: *Ctx,
|
||||||
) ![]const u8 {
|
) ![]const u8 {
|
||||||
const msg = try cdp.getMsg(alloc, _id, void, scanner);
|
const input = try msg.getInput(alloc, void);
|
||||||
log.debug("Req > id {d}, method {s}", .{ msg.id, "emulation.setTouchEmulationEnabled" });
|
log.debug("Req > id {d}, method {s}", .{ input.id, "emulation.setTouchEmulationEnabled" });
|
||||||
|
|
||||||
return result(alloc, msg.id, null, null, msg.sessionID);
|
return result(alloc, input.id, null, null, input.sessionId);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ const server = @import("../server.zig");
|
|||||||
const Ctx = server.Ctx;
|
const Ctx = server.Ctx;
|
||||||
const cdp = @import("cdp.zig");
|
const cdp = @import("cdp.zig");
|
||||||
const result = cdp.result;
|
const result = cdp.result;
|
||||||
const getMsg = cdp.getMsg;
|
const IncomingMessage = @import("msg.zig").IncomingMessage;
|
||||||
|
|
||||||
const log = std.log.scoped(.cdp);
|
const log = std.log.scoped(.cdp);
|
||||||
|
|
||||||
@@ -32,28 +32,26 @@ const Methods = enum {
|
|||||||
|
|
||||||
pub fn fetch(
|
pub fn fetch(
|
||||||
alloc: std.mem.Allocator,
|
alloc: std.mem.Allocator,
|
||||||
id: ?u16,
|
msg: *IncomingMessage,
|
||||||
action: []const u8,
|
action: []const u8,
|
||||||
scanner: *std.json.Scanner,
|
|
||||||
ctx: *Ctx,
|
ctx: *Ctx,
|
||||||
) ![]const u8 {
|
) ![]const u8 {
|
||||||
const method = std.meta.stringToEnum(Methods, action) orelse
|
const method = std.meta.stringToEnum(Methods, action) orelse
|
||||||
return error.UnknownMethod;
|
return error.UnknownMethod;
|
||||||
|
|
||||||
return switch (method) {
|
return switch (method) {
|
||||||
.disable => disable(alloc, id, scanner, ctx),
|
.disable => disable(alloc, msg, ctx),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: noop method
|
// TODO: noop method
|
||||||
fn disable(
|
fn disable(
|
||||||
alloc: std.mem.Allocator,
|
alloc: std.mem.Allocator,
|
||||||
_id: ?u16,
|
msg: *IncomingMessage,
|
||||||
scanner: *std.json.Scanner,
|
|
||||||
_: *Ctx,
|
_: *Ctx,
|
||||||
) ![]const u8 {
|
) ![]const u8 {
|
||||||
const msg = try getMsg(alloc, _id, void, scanner);
|
const input = try msg.getInput(alloc, void);
|
||||||
log.debug("Req > id {d}, method {s}", .{ msg.id, "fetch.disable" });
|
log.debug("Req > id {d}, method {s}", .{ input.id, "fetch.disable" });
|
||||||
|
|
||||||
return result(alloc, msg.id, null, null, msg.sessionID);
|
return result(alloc, input.id, null, null, input.sessionId);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ const server = @import("../server.zig");
|
|||||||
const Ctx = server.Ctx;
|
const Ctx = server.Ctx;
|
||||||
const cdp = @import("cdp.zig");
|
const cdp = @import("cdp.zig");
|
||||||
const result = cdp.result;
|
const result = cdp.result;
|
||||||
const getMsg = cdp.getMsg;
|
const IncomingMessage = @import("msg.zig").IncomingMessage;
|
||||||
const stringify = cdp.stringify;
|
const stringify = cdp.stringify;
|
||||||
|
|
||||||
const log_cdp = std.log.scoped(.cdp);
|
const log_cdp = std.log.scoped(.cdp);
|
||||||
@@ -33,27 +33,25 @@ const Methods = enum {
|
|||||||
|
|
||||||
pub fn log(
|
pub fn log(
|
||||||
alloc: std.mem.Allocator,
|
alloc: std.mem.Allocator,
|
||||||
id: ?u16,
|
msg: *IncomingMessage,
|
||||||
action: []const u8,
|
action: []const u8,
|
||||||
scanner: *std.json.Scanner,
|
|
||||||
ctx: *Ctx,
|
ctx: *Ctx,
|
||||||
) ![]const u8 {
|
) ![]const u8 {
|
||||||
const method = std.meta.stringToEnum(Methods, action) orelse
|
const method = std.meta.stringToEnum(Methods, action) orelse
|
||||||
return error.UnknownMethod;
|
return error.UnknownMethod;
|
||||||
|
|
||||||
return switch (method) {
|
return switch (method) {
|
||||||
.enable => enable(alloc, id, scanner, ctx),
|
.enable => enable(alloc, msg, ctx),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
fn enable(
|
fn enable(
|
||||||
alloc: std.mem.Allocator,
|
alloc: std.mem.Allocator,
|
||||||
_id: ?u16,
|
msg: *IncomingMessage,
|
||||||
scanner: *std.json.Scanner,
|
|
||||||
_: *Ctx,
|
_: *Ctx,
|
||||||
) ![]const u8 {
|
) ![]const u8 {
|
||||||
const msg = try getMsg(alloc, _id, void, scanner);
|
const input = try msg.getInput(alloc, void);
|
||||||
log_cdp.debug("Req > id {d}, method {s}", .{ msg.id, "log.enable" });
|
log_cdp.debug("Req > id {d}, method {s}", .{ input.id, "log.enable" });
|
||||||
|
|
||||||
return result(alloc, msg.id, null, null, msg.sessionID);
|
return result(alloc, input.id, null, null, input.sessionId);
|
||||||
}
|
}
|
||||||
|
|||||||
214
src/cdp/msg.zig
Normal file
214
src/cdp/msg.zig
Normal file
@@ -0,0 +1,214 @@
|
|||||||
|
// Copyright (C) 2023-2024 Lightpanda (Selecy SAS)
|
||||||
|
//
|
||||||
|
// Francis Bouvier <francis@lightpanda.io>
|
||||||
|
// Pierre Tachoire <pierre@lightpanda.io>
|
||||||
|
//
|
||||||
|
// This program is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU Affero General Public License as
|
||||||
|
// published by the Free Software Foundation, either version 3 of the
|
||||||
|
// License, or (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU Affero General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU Affero General Public License
|
||||||
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
const std = @import("std");
|
||||||
|
|
||||||
|
// Parse incoming protocol message in json format.
|
||||||
|
pub const IncomingMessage = struct {
|
||||||
|
scanner: std.json.Scanner,
|
||||||
|
json: []const u8,
|
||||||
|
|
||||||
|
obj_begin: bool = false,
|
||||||
|
obj_end: bool = false,
|
||||||
|
|
||||||
|
id: ?u16 = null,
|
||||||
|
scan_sessionId: bool = false,
|
||||||
|
sessionId: ?[]const u8 = null,
|
||||||
|
method: ?[]const u8 = null,
|
||||||
|
params_skip: bool = false,
|
||||||
|
|
||||||
|
pub fn init(alloc: std.mem.Allocator, json: []const u8) IncomingMessage {
|
||||||
|
return .{
|
||||||
|
.json = json,
|
||||||
|
.scanner = std.json.Scanner.initCompleteInput(alloc, json),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn deinit(self: *IncomingMessage) void {
|
||||||
|
self.scanner.deinit();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn scanUntil(self: *IncomingMessage, key: []const u8) !void {
|
||||||
|
while (true) {
|
||||||
|
switch (try self.scanner.next()) {
|
||||||
|
.end_of_document => return error.EndOfDocument,
|
||||||
|
.object_begin => {
|
||||||
|
if (self.obj_begin) return error.InvalidObjectBegin;
|
||||||
|
self.obj_begin = true;
|
||||||
|
},
|
||||||
|
.object_end => {
|
||||||
|
if (!self.obj_begin) return error.InvalidObjectEnd;
|
||||||
|
if (self.obj_end) return error.InvalidObjectEnd;
|
||||||
|
self.obj_end = true;
|
||||||
|
},
|
||||||
|
.string => |s| {
|
||||||
|
// is the key what we expects?
|
||||||
|
if (std.mem.eql(u8, s, key)) return;
|
||||||
|
|
||||||
|
// save other known keys
|
||||||
|
if (std.mem.eql(u8, s, "id")) try self.scanId();
|
||||||
|
if (std.mem.eql(u8, s, "sessionId")) try self.scanSessionId();
|
||||||
|
if (std.mem.eql(u8, s, "method")) try self.scanMethod();
|
||||||
|
if (std.mem.eql(u8, s, "params")) try self.scanParams();
|
||||||
|
|
||||||
|
// TODO should we skip unknown key?
|
||||||
|
},
|
||||||
|
else => return error.InvalidToken,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn scanId(self: *IncomingMessage) !void {
|
||||||
|
const t = try self.scanner.next();
|
||||||
|
if (t != .number) return error.InvalidId;
|
||||||
|
self.id = try std.fmt.parseUnsigned(u16, t.number, 10);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn getId(self: *IncomingMessage) !u16 {
|
||||||
|
if (self.id != null) return self.id.?;
|
||||||
|
|
||||||
|
try self.scanUntil("id");
|
||||||
|
try self.scanId();
|
||||||
|
return self.id.?;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn scanSessionId(self: *IncomingMessage) !void {
|
||||||
|
switch (try self.scanner.next()) {
|
||||||
|
// session id can be null.
|
||||||
|
.null => return,
|
||||||
|
.string => |s| self.sessionId = s,
|
||||||
|
else => return error.InvalidSessionId,
|
||||||
|
}
|
||||||
|
|
||||||
|
self.scan_sessionId = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn getSessionId(self: *IncomingMessage) !?[]const u8 {
|
||||||
|
if (self.scan_sessionId) return self.sessionId;
|
||||||
|
|
||||||
|
self.scanUntil("sessionId") catch |err| {
|
||||||
|
if (err != error.EndOfDocument) return err;
|
||||||
|
// if the document doesn't contains any session id key, we must
|
||||||
|
// return null value.
|
||||||
|
self.scan_sessionId = true;
|
||||||
|
return null;
|
||||||
|
};
|
||||||
|
try self.scanSessionId();
|
||||||
|
return self.sessionId;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn scanMethod(self: *IncomingMessage) !void {
|
||||||
|
const t = try self.scanner.next();
|
||||||
|
if (t != .string) return error.InvalidMethod;
|
||||||
|
self.method = t.string;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn getMethod(self: *IncomingMessage) ![]const u8 {
|
||||||
|
if (self.method != null) return self.method.?;
|
||||||
|
|
||||||
|
try self.scanUntil("method");
|
||||||
|
try self.scanMethod();
|
||||||
|
return self.method.?;
|
||||||
|
}
|
||||||
|
|
||||||
|
// scanParams skip found parameters b/c if we encounter params *before*
|
||||||
|
// asking for getParams, we don't know how to parse them.
|
||||||
|
fn scanParams(self: *IncomingMessage) !void {
|
||||||
|
const tt = try self.scanner.peekNextTokenType();
|
||||||
|
if (tt != .object_begin) return error.InvalidParams;
|
||||||
|
try self.scanner.skipValue();
|
||||||
|
self.params_skip = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// getParams restart the JSON parsing
|
||||||
|
fn getParams(self: *IncomingMessage, alloc: std.mem.Allocator, T: type) !T {
|
||||||
|
if (T == void) return void{};
|
||||||
|
|
||||||
|
if (self.params_skip) {
|
||||||
|
// TODO if the params have been skipped, we have to retart the
|
||||||
|
// parsing from start.
|
||||||
|
return error.SkippedParams;
|
||||||
|
}
|
||||||
|
|
||||||
|
try self.scanUntil("params");
|
||||||
|
|
||||||
|
// parse "params"
|
||||||
|
const options = std.json.ParseOptions{
|
||||||
|
.max_value_len = self.scanner.input.len,
|
||||||
|
.allocate = .alloc_if_needed,
|
||||||
|
};
|
||||||
|
return try std.json.innerParse(T, alloc, &self.scanner, options);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn getInput(self: *IncomingMessage, alloc: std.mem.Allocator, T: type) !struct { id: u16, sessionId: ?[]const u8, params: T } {
|
||||||
|
return .{
|
||||||
|
.params = try self.getParams(alloc, T),
|
||||||
|
.id = try self.getId(),
|
||||||
|
.sessionId = try self.getSessionId(),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
test "read incoming message" {
|
||||||
|
const inputs = [_][]const u8{
|
||||||
|
\\{"id":1,"method":"foo","sessionId":"bar","params":{"bar":"baz"}}
|
||||||
|
,
|
||||||
|
\\{"params":{"bar":"baz"},"id":1,"method":"foo","sessionId":"bar"}
|
||||||
|
,
|
||||||
|
\\{"sessionId":"bar","params":{"bar":"baz"},"id":1,"method":"foo"}
|
||||||
|
,
|
||||||
|
\\{"method":"foo","sessionId":"bar","params":{"bar":"baz"},"id":1}
|
||||||
|
,
|
||||||
|
};
|
||||||
|
|
||||||
|
for (inputs) |input| {
|
||||||
|
var msg = IncomingMessage.init(std.testing.allocator, input);
|
||||||
|
defer msg.deinit();
|
||||||
|
|
||||||
|
try std.testing.expectEqual(1, try msg.getId());
|
||||||
|
try std.testing.expectEqualSlices(u8, "foo", try msg.getMethod());
|
||||||
|
try std.testing.expectEqualSlices(u8, "bar", (try msg.getSessionId()).?);
|
||||||
|
|
||||||
|
const T = struct { bar: []const u8 };
|
||||||
|
const in = msg.getInput(std.testing.allocator, T) catch |err| {
|
||||||
|
if (err != error.SkippedParams) return err;
|
||||||
|
// TODO remove this check when params in the beginning is handled.
|
||||||
|
continue;
|
||||||
|
};
|
||||||
|
try std.testing.expectEqualSlices(u8, "baz", in.params.bar);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
test "read incoming message with null session id" {
|
||||||
|
const inputs = [_][]const u8{
|
||||||
|
\\{"id":1}
|
||||||
|
,
|
||||||
|
\\{"params":{"bar":"baz"},"id":1,"method":"foo"}
|
||||||
|
,
|
||||||
|
\\{"sessionId":null,"params":{"bar":"baz"},"id":1,"method":"foo"}
|
||||||
|
,
|
||||||
|
};
|
||||||
|
|
||||||
|
for (inputs) |input| {
|
||||||
|
var msg = IncomingMessage.init(std.testing.allocator, input);
|
||||||
|
defer msg.deinit();
|
||||||
|
|
||||||
|
try std.testing.expect(try msg.getSessionId() == null);
|
||||||
|
try std.testing.expectEqual(1, try msg.getId());
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -22,7 +22,7 @@ const server = @import("../server.zig");
|
|||||||
const Ctx = server.Ctx;
|
const Ctx = server.Ctx;
|
||||||
const cdp = @import("cdp.zig");
|
const cdp = @import("cdp.zig");
|
||||||
const result = cdp.result;
|
const result = cdp.result;
|
||||||
const getMsg = cdp.getMsg;
|
const IncomingMessage = @import("msg.zig").IncomingMessage;
|
||||||
|
|
||||||
const log = std.log.scoped(.cdp);
|
const log = std.log.scoped(.cdp);
|
||||||
|
|
||||||
@@ -33,45 +33,40 @@ const Methods = enum {
|
|||||||
|
|
||||||
pub fn network(
|
pub fn network(
|
||||||
alloc: std.mem.Allocator,
|
alloc: std.mem.Allocator,
|
||||||
id: ?u16,
|
msg: *IncomingMessage,
|
||||||
action: []const u8,
|
action: []const u8,
|
||||||
scanner: *std.json.Scanner,
|
|
||||||
ctx: *Ctx,
|
ctx: *Ctx,
|
||||||
) ![]const u8 {
|
) ![]const u8 {
|
||||||
const method = std.meta.stringToEnum(Methods, action) orelse
|
const method = std.meta.stringToEnum(Methods, action) orelse
|
||||||
return error.UnknownMethod;
|
return error.UnknownMethod;
|
||||||
|
|
||||||
return switch (method) {
|
return switch (method) {
|
||||||
.enable => enable(alloc, id, scanner, ctx),
|
.enable => enable(alloc, msg, ctx),
|
||||||
.setCacheDisabled => setCacheDisabled(alloc, id, scanner, ctx),
|
.setCacheDisabled => setCacheDisabled(alloc, msg, ctx),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
fn enable(
|
fn enable(
|
||||||
alloc: std.mem.Allocator,
|
alloc: std.mem.Allocator,
|
||||||
_id: ?u16,
|
msg: *IncomingMessage,
|
||||||
scanner: *std.json.Scanner,
|
|
||||||
_: *Ctx,
|
_: *Ctx,
|
||||||
) ![]const u8 {
|
) ![]const u8 {
|
||||||
|
|
||||||
// input
|
// input
|
||||||
const msg = try getMsg(alloc, _id, void, scanner);
|
const input = try msg.getInput(alloc, void);
|
||||||
log.debug("Req > id {d}, method {s}", .{ msg.id, "network.enable" });
|
log.debug("Req > id {d}, method {s}", .{ input.id, "network.enable" });
|
||||||
|
|
||||||
return result(alloc, msg.id, null, null, msg.sessionID);
|
return result(alloc, input.id, null, null, input.sessionId);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: noop method
|
// TODO: noop method
|
||||||
fn setCacheDisabled(
|
fn setCacheDisabled(
|
||||||
alloc: std.mem.Allocator,
|
alloc: std.mem.Allocator,
|
||||||
_id: ?u16,
|
msg: *IncomingMessage,
|
||||||
scanner: *std.json.Scanner,
|
|
||||||
_: *Ctx,
|
_: *Ctx,
|
||||||
) ![]const u8 {
|
) ![]const u8 {
|
||||||
|
|
||||||
// input
|
// input
|
||||||
const msg = try getMsg(alloc, _id, void, scanner);
|
const input = try msg.getInput(alloc, void);
|
||||||
log.debug("Req > id {d}, method {s}", .{ msg.id, "network.setCacheDisabled" });
|
log.debug("Req > id {d}, method {s}", .{ input.id, "network.setCacheDisabled" });
|
||||||
|
|
||||||
return result(alloc, msg.id, null, null, msg.sessionID);
|
return result(alloc, input.id, null, null, input.sessionId);
|
||||||
}
|
}
|
||||||
|
|||||||
113
src/cdp/page.zig
113
src/cdp/page.zig
@@ -22,9 +22,9 @@ const server = @import("../server.zig");
|
|||||||
const Ctx = server.Ctx;
|
const Ctx = server.Ctx;
|
||||||
const cdp = @import("cdp.zig");
|
const cdp = @import("cdp.zig");
|
||||||
const result = cdp.result;
|
const result = cdp.result;
|
||||||
const getMsg = cdp.getMsg;
|
|
||||||
const stringify = cdp.stringify;
|
const stringify = cdp.stringify;
|
||||||
const sendEvent = cdp.sendEvent;
|
const sendEvent = cdp.sendEvent;
|
||||||
|
const IncomingMessage = @import("msg.zig").IncomingMessage;
|
||||||
|
|
||||||
const log = std.log.scoped(.cdp);
|
const log = std.log.scoped(.cdp);
|
||||||
|
|
||||||
@@ -41,35 +41,32 @@ const Methods = enum {
|
|||||||
|
|
||||||
pub fn page(
|
pub fn page(
|
||||||
alloc: std.mem.Allocator,
|
alloc: std.mem.Allocator,
|
||||||
id: ?u16,
|
msg: *IncomingMessage,
|
||||||
action: []const u8,
|
action: []const u8,
|
||||||
scanner: *std.json.Scanner,
|
|
||||||
ctx: *Ctx,
|
ctx: *Ctx,
|
||||||
) ![]const u8 {
|
) ![]const u8 {
|
||||||
const method = std.meta.stringToEnum(Methods, action) orelse
|
const method = std.meta.stringToEnum(Methods, action) orelse
|
||||||
return error.UnknownMethod;
|
return error.UnknownMethod;
|
||||||
return switch (method) {
|
return switch (method) {
|
||||||
.enable => enable(alloc, id, scanner, ctx),
|
.enable => enable(alloc, msg, ctx),
|
||||||
.getFrameTree => getFrameTree(alloc, id, scanner, ctx),
|
.getFrameTree => getFrameTree(alloc, msg, ctx),
|
||||||
.setLifecycleEventsEnabled => setLifecycleEventsEnabled(alloc, id, scanner, ctx),
|
.setLifecycleEventsEnabled => setLifecycleEventsEnabled(alloc, msg, ctx),
|
||||||
.addScriptToEvaluateOnNewDocument => addScriptToEvaluateOnNewDocument(alloc, id, scanner, ctx),
|
.addScriptToEvaluateOnNewDocument => addScriptToEvaluateOnNewDocument(alloc, msg, ctx),
|
||||||
.createIsolatedWorld => createIsolatedWorld(alloc, id, scanner, ctx),
|
.createIsolatedWorld => createIsolatedWorld(alloc, msg, ctx),
|
||||||
.navigate => navigate(alloc, id, scanner, ctx),
|
.navigate => navigate(alloc, msg, ctx),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
fn enable(
|
fn enable(
|
||||||
alloc: std.mem.Allocator,
|
alloc: std.mem.Allocator,
|
||||||
_id: ?u16,
|
msg: *IncomingMessage,
|
||||||
scanner: *std.json.Scanner,
|
|
||||||
_: *Ctx,
|
_: *Ctx,
|
||||||
) ![]const u8 {
|
) ![]const u8 {
|
||||||
|
|
||||||
// input
|
// input
|
||||||
const msg = try getMsg(alloc, _id, void, scanner);
|
const input = try msg.getInput(alloc, void);
|
||||||
log.debug("Req > id {d}, method {s}", .{ msg.id, "page.enable" });
|
log.debug("Req > id {d}, method {s}", .{ input.id, "page.enable" });
|
||||||
|
|
||||||
return result(alloc, msg.id, null, null, msg.sessionID);
|
return result(alloc, input.id, null, null, input.sessionId);
|
||||||
}
|
}
|
||||||
|
|
||||||
const Frame = struct {
|
const Frame = struct {
|
||||||
@@ -89,14 +86,12 @@ const Frame = struct {
|
|||||||
|
|
||||||
fn getFrameTree(
|
fn getFrameTree(
|
||||||
alloc: std.mem.Allocator,
|
alloc: std.mem.Allocator,
|
||||||
_id: ?u16,
|
msg: *IncomingMessage,
|
||||||
scanner: *std.json.Scanner,
|
|
||||||
ctx: *Ctx,
|
ctx: *Ctx,
|
||||||
) ![]const u8 {
|
) ![]const u8 {
|
||||||
|
|
||||||
// input
|
// input
|
||||||
const msg = try cdp.getMsg(alloc, _id, void, scanner);
|
const input = try msg.getInput(alloc, void);
|
||||||
log.debug("Req > id {d}, method {s}", .{ msg.id, "page.getFrameTree" });
|
log.debug("Req > id {d}, method {s}", .{ input.id, "page.getFrameTree" });
|
||||||
|
|
||||||
// output
|
// output
|
||||||
const FrameTree = struct {
|
const FrameTree = struct {
|
||||||
@@ -135,27 +130,25 @@ fn getFrameTree(
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
return result(alloc, msg.id, FrameTree, frameTree, msg.sessionID);
|
return result(alloc, input.id, FrameTree, frameTree, input.sessionId);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn setLifecycleEventsEnabled(
|
fn setLifecycleEventsEnabled(
|
||||||
alloc: std.mem.Allocator,
|
alloc: std.mem.Allocator,
|
||||||
_id: ?u16,
|
msg: *IncomingMessage,
|
||||||
scanner: *std.json.Scanner,
|
|
||||||
ctx: *Ctx,
|
ctx: *Ctx,
|
||||||
) ![]const u8 {
|
) ![]const u8 {
|
||||||
|
|
||||||
// input
|
// input
|
||||||
const Params = struct {
|
const Params = struct {
|
||||||
enabled: bool,
|
enabled: bool,
|
||||||
};
|
};
|
||||||
const msg = try getMsg(alloc, _id, Params, scanner);
|
const input = try msg.getInput(alloc, Params);
|
||||||
log.debug("Req > id {d}, method {s}", .{ msg.id, "page.setLifecycleEventsEnabled" });
|
log.debug("Req > id {d}, method {s}", .{ input.id, "page.setLifecycleEventsEnabled" });
|
||||||
|
|
||||||
ctx.state.page_life_cycle_events = true;
|
ctx.state.page_life_cycle_events = true;
|
||||||
|
|
||||||
// output
|
// output
|
||||||
return result(alloc, msg.id, null, null, msg.sessionID);
|
return result(alloc, input.id, null, null, input.sessionId);
|
||||||
}
|
}
|
||||||
|
|
||||||
const LifecycleEvent = struct {
|
const LifecycleEvent = struct {
|
||||||
@@ -168,11 +161,9 @@ const LifecycleEvent = struct {
|
|||||||
// TODO: hard coded method
|
// TODO: hard coded method
|
||||||
fn addScriptToEvaluateOnNewDocument(
|
fn addScriptToEvaluateOnNewDocument(
|
||||||
alloc: std.mem.Allocator,
|
alloc: std.mem.Allocator,
|
||||||
_id: ?u16,
|
msg: *IncomingMessage,
|
||||||
scanner: *std.json.Scanner,
|
|
||||||
_: *Ctx,
|
_: *Ctx,
|
||||||
) ![]const u8 {
|
) ![]const u8 {
|
||||||
|
|
||||||
// input
|
// input
|
||||||
const Params = struct {
|
const Params = struct {
|
||||||
source: []const u8,
|
source: []const u8,
|
||||||
@@ -180,8 +171,8 @@ fn addScriptToEvaluateOnNewDocument(
|
|||||||
includeCommandLineAPI: bool = false,
|
includeCommandLineAPI: bool = false,
|
||||||
runImmediately: bool = false,
|
runImmediately: bool = false,
|
||||||
};
|
};
|
||||||
const msg = try getMsg(alloc, _id, Params, scanner);
|
const input = try msg.getInput(alloc, Params);
|
||||||
log.debug("Req > id {d}, method {s}", .{ msg.id, "page.addScriptToEvaluateOnNewDocument" });
|
log.debug("Req > id {d}, method {s}", .{ input.id, "page.addScriptToEvaluateOnNewDocument" });
|
||||||
|
|
||||||
// output
|
// output
|
||||||
const Res = struct {
|
const Res = struct {
|
||||||
@@ -199,27 +190,24 @@ fn addScriptToEvaluateOnNewDocument(
|
|||||||
try writer.writeAll(" }");
|
try writer.writeAll(" }");
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
return result(alloc, msg.id, Res, Res{}, msg.sessionID);
|
return result(alloc, input.id, Res, Res{}, input.sessionId);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: hard coded method
|
// TODO: hard coded method
|
||||||
fn createIsolatedWorld(
|
fn createIsolatedWorld(
|
||||||
alloc: std.mem.Allocator,
|
alloc: std.mem.Allocator,
|
||||||
_id: ?u16,
|
msg: *IncomingMessage,
|
||||||
scanner: *std.json.Scanner,
|
|
||||||
ctx: *Ctx,
|
ctx: *Ctx,
|
||||||
) ![]const u8 {
|
) ![]const u8 {
|
||||||
|
|
||||||
// input
|
// input
|
||||||
const Params = struct {
|
const Params = struct {
|
||||||
frameId: []const u8,
|
frameId: []const u8,
|
||||||
worldName: []const u8,
|
worldName: []const u8,
|
||||||
grantUniveralAccess: bool,
|
grantUniveralAccess: bool,
|
||||||
};
|
};
|
||||||
const msg = try getMsg(alloc, _id, Params, scanner);
|
const input = try msg.getInput(alloc, Params);
|
||||||
std.debug.assert(msg.sessionID != null);
|
std.debug.assert(input.sessionId != null);
|
||||||
log.debug("Req > id {d}, method {s}", .{ msg.id, "page.createIsolatedWorld" });
|
log.debug("Req > id {d}, method {s}", .{ input.id, "page.createIsolatedWorld" });
|
||||||
const params = msg.params.?;
|
|
||||||
|
|
||||||
// noop executionContextCreated event
|
// noop executionContextCreated event
|
||||||
try Runtime.executionContextCreated(
|
try Runtime.executionContextCreated(
|
||||||
@@ -227,15 +215,15 @@ fn createIsolatedWorld(
|
|||||||
ctx,
|
ctx,
|
||||||
0,
|
0,
|
||||||
"",
|
"",
|
||||||
params.worldName,
|
input.params.worldName,
|
||||||
// TODO: hard coded ID
|
// TODO: hard coded ID
|
||||||
"7102379147004877974.3265385113993241162",
|
"7102379147004877974.3265385113993241162",
|
||||||
.{
|
.{
|
||||||
.isDefault = false,
|
.isDefault = false,
|
||||||
.type = "isolated",
|
.type = "isolated",
|
||||||
.frameId = params.frameId,
|
.frameId = input.params.frameId,
|
||||||
},
|
},
|
||||||
msg.sessionID,
|
input.sessionId,
|
||||||
);
|
);
|
||||||
|
|
||||||
// output
|
// output
|
||||||
@@ -243,16 +231,14 @@ fn createIsolatedWorld(
|
|||||||
executionContextId: u8 = 0,
|
executionContextId: u8 = 0,
|
||||||
};
|
};
|
||||||
|
|
||||||
return result(alloc, msg.id, Resp, .{}, msg.sessionID);
|
return result(alloc, input.id, Resp, .{}, input.sessionId);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn navigate(
|
fn navigate(
|
||||||
alloc: std.mem.Allocator,
|
alloc: std.mem.Allocator,
|
||||||
_id: ?u16,
|
msg: *IncomingMessage,
|
||||||
scanner: *std.json.Scanner,
|
|
||||||
ctx: *Ctx,
|
ctx: *Ctx,
|
||||||
) ![]const u8 {
|
) ![]const u8 {
|
||||||
|
|
||||||
// input
|
// input
|
||||||
const Params = struct {
|
const Params = struct {
|
||||||
url: []const u8,
|
url: []const u8,
|
||||||
@@ -261,13 +247,12 @@ fn navigate(
|
|||||||
frameId: ?[]const u8 = null,
|
frameId: ?[]const u8 = null,
|
||||||
referrerPolicy: ?[]const u8 = null, // TODO: enum
|
referrerPolicy: ?[]const u8 = null, // TODO: enum
|
||||||
};
|
};
|
||||||
const msg = try getMsg(alloc, _id, Params, scanner);
|
const input = try msg.getInput(alloc, Params);
|
||||||
std.debug.assert(msg.sessionID != null);
|
std.debug.assert(input.sessionId != null);
|
||||||
log.debug("Req > id {d}, method {s}", .{ msg.id, "page.navigate" });
|
log.debug("Req > id {d}, method {s}", .{ input.id, "page.navigate" });
|
||||||
const params = msg.params.?;
|
|
||||||
|
|
||||||
// change state
|
// change state
|
||||||
ctx.state.url = params.url;
|
ctx.state.url = input.params.url;
|
||||||
// TODO: hard coded ID
|
// TODO: hard coded ID
|
||||||
ctx.state.loaderID = "AF8667A203C5392DBE9AC290044AA4C2";
|
ctx.state.loaderID = "AF8667A203C5392DBE9AC290044AA4C2";
|
||||||
|
|
||||||
@@ -289,7 +274,7 @@ fn navigate(
|
|||||||
"Page.frameStartedLoading",
|
"Page.frameStartedLoading",
|
||||||
FrameStartedLoading,
|
FrameStartedLoading,
|
||||||
frame_started_loading,
|
frame_started_loading,
|
||||||
msg.sessionID,
|
input.sessionId,
|
||||||
);
|
);
|
||||||
if (ctx.state.page_life_cycle_events) {
|
if (ctx.state.page_life_cycle_events) {
|
||||||
life_event.name = "init";
|
life_event.name = "init";
|
||||||
@@ -300,7 +285,7 @@ fn navigate(
|
|||||||
"Page.lifecycleEvent",
|
"Page.lifecycleEvent",
|
||||||
LifecycleEvent,
|
LifecycleEvent,
|
||||||
life_event,
|
life_event,
|
||||||
msg.sessionID,
|
input.sessionId,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -330,14 +315,14 @@ fn navigate(
|
|||||||
.frameId = ctx.state.frameID,
|
.frameId = ctx.state.frameID,
|
||||||
.loaderId = ctx.state.loaderID,
|
.loaderId = ctx.state.loaderID,
|
||||||
};
|
};
|
||||||
const res = try result(alloc, msg.id, Resp, resp, msg.sessionID);
|
const res = try result(alloc, input.id, Resp, resp, input.sessionId);
|
||||||
try server.sendAsync(ctx, res);
|
try server.sendAsync(ctx, res);
|
||||||
|
|
||||||
// TODO: at this point do we need async the following actions to be async?
|
// TODO: at this point do we need async the following actions to be async?
|
||||||
|
|
||||||
// Send Runtime.executionContextsCleared event
|
// Send Runtime.executionContextsCleared event
|
||||||
// TODO: noop event, we have no env context at this point, is it necesarry?
|
// TODO: noop event, we have no env context at this point, is it necesarry?
|
||||||
try sendEvent(alloc, ctx, "Runtime.executionContextsCleared", void, {}, msg.sessionID);
|
try sendEvent(alloc, ctx, "Runtime.executionContextsCleared", void, {}, input.sessionId);
|
||||||
|
|
||||||
// Launch navigate
|
// Launch navigate
|
||||||
const p = try ctx.browser.session.createPage();
|
const p = try ctx.browser.session.createPage();
|
||||||
@@ -349,7 +334,7 @@ fn navigate(
|
|||||||
.{ctx.state.frameID},
|
.{ctx.state.frameID},
|
||||||
);
|
);
|
||||||
defer alloc.free(auxData);
|
defer alloc.free(auxData);
|
||||||
try p.navigate(params.url, auxData);
|
try p.navigate(input.params.url, auxData);
|
||||||
|
|
||||||
// Events
|
// Events
|
||||||
|
|
||||||
@@ -364,7 +349,7 @@ fn navigate(
|
|||||||
"Page.lifecycleEvent",
|
"Page.lifecycleEvent",
|
||||||
LifecycleEvent,
|
LifecycleEvent,
|
||||||
life_event,
|
life_event,
|
||||||
msg.sessionID,
|
input.sessionId,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -388,7 +373,7 @@ fn navigate(
|
|||||||
"Page.frameNavigated",
|
"Page.frameNavigated",
|
||||||
FrameNavigated,
|
FrameNavigated,
|
||||||
frame_navigated,
|
frame_navigated,
|
||||||
msg.sessionID,
|
input.sessionId,
|
||||||
);
|
);
|
||||||
|
|
||||||
// domContentEventFired event
|
// domContentEventFired event
|
||||||
@@ -400,7 +385,7 @@ fn navigate(
|
|||||||
"Page.domContentEventFired",
|
"Page.domContentEventFired",
|
||||||
cdp.TimestampEvent,
|
cdp.TimestampEvent,
|
||||||
ts_event,
|
ts_event,
|
||||||
msg.sessionID,
|
input.sessionId,
|
||||||
);
|
);
|
||||||
|
|
||||||
// lifecycle DOMContentLoaded event
|
// lifecycle DOMContentLoaded event
|
||||||
@@ -414,7 +399,7 @@ fn navigate(
|
|||||||
"Page.lifecycleEvent",
|
"Page.lifecycleEvent",
|
||||||
LifecycleEvent,
|
LifecycleEvent,
|
||||||
life_event,
|
life_event,
|
||||||
msg.sessionID,
|
input.sessionId,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -427,7 +412,7 @@ fn navigate(
|
|||||||
"Page.loadEventFired",
|
"Page.loadEventFired",
|
||||||
cdp.TimestampEvent,
|
cdp.TimestampEvent,
|
||||||
ts_event,
|
ts_event,
|
||||||
msg.sessionID,
|
input.sessionId,
|
||||||
);
|
);
|
||||||
|
|
||||||
// lifecycle DOMContentLoaded event
|
// lifecycle DOMContentLoaded event
|
||||||
@@ -441,7 +426,7 @@ fn navigate(
|
|||||||
"Page.lifecycleEvent",
|
"Page.lifecycleEvent",
|
||||||
LifecycleEvent,
|
LifecycleEvent,
|
||||||
life_event,
|
life_event,
|
||||||
msg.sessionID,
|
input.sessionId,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -453,7 +438,7 @@ fn navigate(
|
|||||||
"Page.frameStoppedLoading",
|
"Page.frameStoppedLoading",
|
||||||
FrameStoppedLoading,
|
FrameStoppedLoading,
|
||||||
.{ .frameId = ctx.state.frameID },
|
.{ .frameId = ctx.state.frameID },
|
||||||
msg.sessionID,
|
input.sessionId,
|
||||||
);
|
);
|
||||||
|
|
||||||
return "";
|
return "";
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ const server = @import("../server.zig");
|
|||||||
const Ctx = server.Ctx;
|
const Ctx = server.Ctx;
|
||||||
const cdp = @import("cdp.zig");
|
const cdp = @import("cdp.zig");
|
||||||
const result = cdp.result;
|
const result = cdp.result;
|
||||||
const getMsg = cdp.getMsg;
|
const IncomingMessage = @import("msg.zig").IncomingMessage;
|
||||||
|
|
||||||
const log = std.log.scoped(.cdp);
|
const log = std.log.scoped(.cdp);
|
||||||
|
|
||||||
@@ -32,29 +32,26 @@ const Methods = enum {
|
|||||||
|
|
||||||
pub fn performance(
|
pub fn performance(
|
||||||
alloc: std.mem.Allocator,
|
alloc: std.mem.Allocator,
|
||||||
id: ?u16,
|
msg: *IncomingMessage,
|
||||||
action: []const u8,
|
action: []const u8,
|
||||||
scanner: *std.json.Scanner,
|
|
||||||
ctx: *Ctx,
|
ctx: *Ctx,
|
||||||
) ![]const u8 {
|
) ![]const u8 {
|
||||||
const method = std.meta.stringToEnum(Methods, action) orelse
|
const method = std.meta.stringToEnum(Methods, action) orelse
|
||||||
return error.UnknownMethod;
|
return error.UnknownMethod;
|
||||||
|
|
||||||
return switch (method) {
|
return switch (method) {
|
||||||
.enable => enable(alloc, id, scanner, ctx),
|
.enable => enable(alloc, msg, ctx),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
fn enable(
|
fn enable(
|
||||||
alloc: std.mem.Allocator,
|
alloc: std.mem.Allocator,
|
||||||
_id: ?u16,
|
msg: *IncomingMessage,
|
||||||
scanner: *std.json.Scanner,
|
|
||||||
_: *Ctx,
|
_: *Ctx,
|
||||||
) ![]const u8 {
|
) ![]const u8 {
|
||||||
|
|
||||||
// input
|
// input
|
||||||
const msg = try getMsg(alloc, _id, void, scanner);
|
const input = try msg.getInput(alloc, void);
|
||||||
log.debug("Req > id {d}, method {s}", .{ msg.id, "performance.enable" });
|
log.debug("Req > id {d}, method {s}", .{ input.id, "performance.enable" });
|
||||||
|
|
||||||
return result(alloc, msg.id, null, null, msg.sessionID);
|
return result(alloc, input.id, null, null, input.sessionId);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ const server = @import("../server.zig");
|
|||||||
const Ctx = server.Ctx;
|
const Ctx = server.Ctx;
|
||||||
const cdp = @import("cdp.zig");
|
const cdp = @import("cdp.zig");
|
||||||
const result = cdp.result;
|
const result = cdp.result;
|
||||||
const getMsg = cdp.getMsg;
|
const IncomingMessage = @import("msg.zig").IncomingMessage;
|
||||||
const stringify = cdp.stringify;
|
const stringify = cdp.stringify;
|
||||||
|
|
||||||
const log = std.log.scoped(.cdp);
|
const log = std.log.scoped(.cdp);
|
||||||
@@ -41,27 +41,23 @@ const Methods = enum {
|
|||||||
|
|
||||||
pub fn runtime(
|
pub fn runtime(
|
||||||
alloc: std.mem.Allocator,
|
alloc: std.mem.Allocator,
|
||||||
id: ?u16,
|
msg: *IncomingMessage,
|
||||||
action: []const u8,
|
action: []const u8,
|
||||||
scanner: *std.json.Scanner,
|
|
||||||
s: []const u8,
|
|
||||||
ctx: *Ctx,
|
ctx: *Ctx,
|
||||||
) ![]const u8 {
|
) ![]const u8 {
|
||||||
const method = std.meta.stringToEnum(Methods, action) orelse
|
const method = std.meta.stringToEnum(Methods, action) orelse
|
||||||
// NOTE: we could send it anyway to the JS runtime but it's good to check it
|
// NOTE: we could send it anyway to the JS runtime but it's good to check it
|
||||||
return error.UnknownMethod;
|
return error.UnknownMethod;
|
||||||
return switch (method) {
|
return switch (method) {
|
||||||
.runIfWaitingForDebugger => runIfWaitingForDebugger(alloc, id, scanner, ctx),
|
.runIfWaitingForDebugger => runIfWaitingForDebugger(alloc, msg, ctx),
|
||||||
else => sendInspector(alloc, method, id, s, scanner, ctx),
|
else => sendInspector(alloc, method, msg, ctx),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
fn sendInspector(
|
fn sendInspector(
|
||||||
alloc: std.mem.Allocator,
|
alloc: std.mem.Allocator,
|
||||||
method: Methods,
|
method: Methods,
|
||||||
_id: ?u16,
|
msg: *IncomingMessage,
|
||||||
s: []const u8,
|
|
||||||
scanner: *std.json.Scanner,
|
|
||||||
ctx: *Ctx,
|
ctx: *Ctx,
|
||||||
) ![]const u8 {
|
) ![]const u8 {
|
||||||
|
|
||||||
@@ -69,8 +65,8 @@ fn sendInspector(
|
|||||||
if (std.log.defaultLogEnabled(.debug)) {
|
if (std.log.defaultLogEnabled(.debug)) {
|
||||||
|
|
||||||
// input
|
// input
|
||||||
var script: ?[]const u8 = null;
|
|
||||||
var id: u16 = undefined;
|
var id: u16 = undefined;
|
||||||
|
var script: ?[]const u8 = null;
|
||||||
|
|
||||||
if (method == .evaluate) {
|
if (method == .evaluate) {
|
||||||
const Params = struct {
|
const Params = struct {
|
||||||
@@ -81,11 +77,10 @@ fn sendInspector(
|
|||||||
userGesture: ?bool = null,
|
userGesture: ?bool = null,
|
||||||
};
|
};
|
||||||
|
|
||||||
const msg = try getMsg(alloc, _id, Params, scanner);
|
const input = try msg.getInput(alloc, Params);
|
||||||
log.debug("Req > id {d}, method {s} (script saved on cache)", .{ msg.id, "runtime.evaluate" });
|
log.debug("Req > id {d}, method {s} (script saved on cache)", .{ input.id, "runtime.evaluate" });
|
||||||
const params = msg.params.?;
|
script = input.params.expression;
|
||||||
script = params.expression;
|
id = input.id;
|
||||||
id = msg.id;
|
|
||||||
} else if (method == .callFunctionOn) {
|
} else if (method == .callFunctionOn) {
|
||||||
const Params = struct {
|
const Params = struct {
|
||||||
functionDeclaration: []const u8,
|
functionDeclaration: []const u8,
|
||||||
@@ -100,11 +95,10 @@ fn sendInspector(
|
|||||||
userGesture: ?bool = null,
|
userGesture: ?bool = null,
|
||||||
};
|
};
|
||||||
|
|
||||||
const msg = try getMsg(alloc, _id, Params, scanner);
|
const input = try msg.getInput(alloc, Params);
|
||||||
log.debug("Req > id {d}, method {s} (script saved on cache)", .{ msg.id, "runtime.callFunctionOn" });
|
log.debug("Req > id {d}, method {s} (script saved on cache)", .{ input.id, "runtime.callFunctionOn" });
|
||||||
const params = msg.params.?;
|
script = input.params.functionDeclaration;
|
||||||
script = params.functionDeclaration;
|
id = input.id;
|
||||||
id = msg.id;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (script) |src| {
|
if (script) |src| {
|
||||||
@@ -115,12 +109,12 @@ fn sendInspector(
|
|||||||
// remove awaitPromise true params
|
// remove awaitPromise true params
|
||||||
// TODO: delete when Promise are correctly handled by zig-js-runtime
|
// TODO: delete when Promise are correctly handled by zig-js-runtime
|
||||||
if (method == .callFunctionOn or method == .evaluate) {
|
if (method == .callFunctionOn or method == .evaluate) {
|
||||||
const buf = try alloc.alloc(u8, s.len + 1);
|
const buf = try alloc.alloc(u8, msg.json.len + 1);
|
||||||
defer alloc.free(buf);
|
defer alloc.free(buf);
|
||||||
_ = std.mem.replace(u8, s, "\"awaitPromise\":true", "\"awaitPromise\":false", buf);
|
_ = std.mem.replace(u8, msg.json, "\"awaitPromise\":true", "\"awaitPromise\":false", buf);
|
||||||
ctx.sendInspector(buf);
|
ctx.sendInspector(buf);
|
||||||
} else {
|
} else {
|
||||||
ctx.sendInspector(s);
|
ctx.sendInspector(msg.json);
|
||||||
}
|
}
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
@@ -166,14 +160,11 @@ pub fn executionContextCreated(
|
|||||||
// should we be passing this also to the JS Inspector?
|
// should we be passing this also to the JS Inspector?
|
||||||
fn runIfWaitingForDebugger(
|
fn runIfWaitingForDebugger(
|
||||||
alloc: std.mem.Allocator,
|
alloc: std.mem.Allocator,
|
||||||
_id: ?u16,
|
msg: *IncomingMessage,
|
||||||
scanner: *std.json.Scanner,
|
|
||||||
_: *Ctx,
|
_: *Ctx,
|
||||||
) ![]const u8 {
|
) ![]const u8 {
|
||||||
|
const input = try msg.getInput(alloc, void);
|
||||||
|
log.debug("Req > id {d}, method {s}", .{ input.id, "runtime.runIfWaitingForDebugger" });
|
||||||
|
|
||||||
// input
|
return result(alloc, input.id, null, null, input.sessionId);
|
||||||
const msg = try getMsg(alloc, _id, void, scanner);
|
|
||||||
log.debug("Req > id {d}, method {s}", .{ msg.id, "runtime.runIfWaitingForDebugger" });
|
|
||||||
|
|
||||||
return result(alloc, msg.id, null, null, msg.sessionID);
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,8 +22,8 @@ const server = @import("../server.zig");
|
|||||||
const Ctx = server.Ctx;
|
const Ctx = server.Ctx;
|
||||||
const cdp = @import("cdp.zig");
|
const cdp = @import("cdp.zig");
|
||||||
const result = cdp.result;
|
const result = cdp.result;
|
||||||
const getMsg = cdp.getMsg;
|
|
||||||
const stringify = cdp.stringify;
|
const stringify = cdp.stringify;
|
||||||
|
const IncomingMessage = @import("msg.zig").IncomingMessage;
|
||||||
|
|
||||||
const log = std.log.scoped(.cdp);
|
const log = std.log.scoped(.cdp);
|
||||||
|
|
||||||
@@ -41,23 +41,22 @@ const Methods = enum {
|
|||||||
|
|
||||||
pub fn target(
|
pub fn target(
|
||||||
alloc: std.mem.Allocator,
|
alloc: std.mem.Allocator,
|
||||||
id: ?u16,
|
msg: *IncomingMessage,
|
||||||
action: []const u8,
|
action: []const u8,
|
||||||
scanner: *std.json.Scanner,
|
|
||||||
ctx: *Ctx,
|
ctx: *Ctx,
|
||||||
) ![]const u8 {
|
) ![]const u8 {
|
||||||
const method = std.meta.stringToEnum(Methods, action) orelse
|
const method = std.meta.stringToEnum(Methods, action) orelse
|
||||||
return error.UnknownMethod;
|
return error.UnknownMethod;
|
||||||
return switch (method) {
|
return switch (method) {
|
||||||
.setDiscoverTargets => setDiscoverTargets(alloc, id, scanner, ctx),
|
.setDiscoverTargets => setDiscoverTargets(alloc, msg, ctx),
|
||||||
.setAutoAttach => setAutoAttach(alloc, id, scanner, ctx),
|
.setAutoAttach => setAutoAttach(alloc, msg, ctx),
|
||||||
.attachToTarget => attachToTarget(alloc, id, scanner, ctx),
|
.attachToTarget => attachToTarget(alloc, msg, ctx),
|
||||||
.getTargetInfo => getTargetInfo(alloc, id, scanner, ctx),
|
.getTargetInfo => getTargetInfo(alloc, msg, ctx),
|
||||||
.getBrowserContexts => getBrowserContexts(alloc, id, scanner, ctx),
|
.getBrowserContexts => getBrowserContexts(alloc, msg, ctx),
|
||||||
.createBrowserContext => createBrowserContext(alloc, id, scanner, ctx),
|
.createBrowserContext => createBrowserContext(alloc, msg, ctx),
|
||||||
.disposeBrowserContext => disposeBrowserContext(alloc, id, scanner, ctx),
|
.disposeBrowserContext => disposeBrowserContext(alloc, msg, ctx),
|
||||||
.createTarget => createTarget(alloc, id, scanner, ctx),
|
.createTarget => createTarget(alloc, msg, ctx),
|
||||||
.closeTarget => closeTarget(alloc, id, scanner, ctx),
|
.closeTarget => closeTarget(alloc, msg, ctx),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -69,17 +68,15 @@ const BrowserContextID = "65618675CB7D3585A95049E9DFE95EA9";
|
|||||||
// TODO: noop method
|
// TODO: noop method
|
||||||
fn setDiscoverTargets(
|
fn setDiscoverTargets(
|
||||||
alloc: std.mem.Allocator,
|
alloc: std.mem.Allocator,
|
||||||
_id: ?u16,
|
msg: *IncomingMessage,
|
||||||
scanner: *std.json.Scanner,
|
|
||||||
_: *Ctx,
|
_: *Ctx,
|
||||||
) ![]const u8 {
|
) ![]const u8 {
|
||||||
|
|
||||||
// input
|
// input
|
||||||
const msg = try getMsg(alloc, _id, void, scanner);
|
const input = try msg.getInput(alloc, void);
|
||||||
log.debug("Req > id {d}, method {s}", .{ msg.id, "target.setDiscoverTargets" });
|
log.debug("Req > id {d}, method {s}", .{ input.id, "target.setDiscoverTargets" });
|
||||||
|
|
||||||
// output
|
// output
|
||||||
return result(alloc, msg.id, null, null, msg.sessionID);
|
return result(alloc, input.id, null, null, input.sessionId);
|
||||||
}
|
}
|
||||||
|
|
||||||
const AttachToTarget = struct {
|
const AttachToTarget = struct {
|
||||||
@@ -104,11 +101,9 @@ const TargetFilter = struct {
|
|||||||
// TODO: noop method
|
// TODO: noop method
|
||||||
fn setAutoAttach(
|
fn setAutoAttach(
|
||||||
alloc: std.mem.Allocator,
|
alloc: std.mem.Allocator,
|
||||||
_id: ?u16,
|
msg: *IncomingMessage,
|
||||||
scanner: *std.json.Scanner,
|
|
||||||
ctx: *Ctx,
|
ctx: *Ctx,
|
||||||
) ![]const u8 {
|
) ![]const u8 {
|
||||||
|
|
||||||
// input
|
// input
|
||||||
const Params = struct {
|
const Params = struct {
|
||||||
autoAttach: bool,
|
autoAttach: bool,
|
||||||
@@ -116,11 +111,11 @@ fn setAutoAttach(
|
|||||||
flatten: bool = true,
|
flatten: bool = true,
|
||||||
filter: ?[]TargetFilter = null,
|
filter: ?[]TargetFilter = null,
|
||||||
};
|
};
|
||||||
const msg = try getMsg(alloc, _id, Params, scanner);
|
const input = try msg.getInput(alloc, Params);
|
||||||
log.debug("Req > id {d}, method {s}", .{ msg.id, "target.setAutoAttach" });
|
log.debug("Req > id {d}, method {s}", .{ input.id, "target.setAutoAttach" });
|
||||||
|
|
||||||
// attachedToTarget event
|
// attachedToTarget event
|
||||||
if (msg.sessionID == null) {
|
if (input.sessionId == null) {
|
||||||
const attached = AttachToTarget{
|
const attached = AttachToTarget{
|
||||||
.sessionId = cdp.BrowserSessionID,
|
.sessionId = cdp.BrowserSessionID,
|
||||||
.targetInfo = .{
|
.targetInfo = .{
|
||||||
@@ -134,14 +129,13 @@ fn setAutoAttach(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// output
|
// output
|
||||||
return result(alloc, msg.id, null, null, msg.sessionID);
|
return result(alloc, input.id, null, null, input.sessionId);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: noop method
|
// TODO: noop method
|
||||||
fn attachToTarget(
|
fn attachToTarget(
|
||||||
alloc: std.mem.Allocator,
|
alloc: std.mem.Allocator,
|
||||||
_id: ?u16,
|
msg: *IncomingMessage,
|
||||||
scanner: *std.json.Scanner,
|
|
||||||
ctx: *Ctx,
|
ctx: *Ctx,
|
||||||
) ![]const u8 {
|
) ![]const u8 {
|
||||||
|
|
||||||
@@ -150,11 +144,11 @@ fn attachToTarget(
|
|||||||
targetId: []const u8,
|
targetId: []const u8,
|
||||||
flatten: bool = true,
|
flatten: bool = true,
|
||||||
};
|
};
|
||||||
const msg = try getMsg(alloc, _id, Params, scanner);
|
const input = try msg.getInput(alloc, Params);
|
||||||
log.debug("Req > id {d}, method {s}", .{ msg.id, "target.setAutoAttach" });
|
log.debug("Req > id {d}, method {s}", .{ input.id, "target.attachToTarget" });
|
||||||
|
|
||||||
// attachedToTarget event
|
// attachedToTarget event
|
||||||
if (msg.sessionID == null) {
|
if (input.sessionId == null) {
|
||||||
const attached = AttachToTarget{
|
const attached = AttachToTarget{
|
||||||
.sessionId = cdp.BrowserSessionID,
|
.sessionId = cdp.BrowserSessionID,
|
||||||
.targetInfo = .{
|
.targetInfo = .{
|
||||||
@@ -172,24 +166,22 @@ fn attachToTarget(
|
|||||||
sessionId: []const u8,
|
sessionId: []const u8,
|
||||||
};
|
};
|
||||||
const output = SessionId{
|
const output = SessionId{
|
||||||
.sessionId = msg.sessionID orelse BrowserContextID,
|
.sessionId = input.sessionId orelse BrowserContextID,
|
||||||
};
|
};
|
||||||
return result(alloc, msg.id, SessionId, output, null);
|
return result(alloc, input.id, SessionId, output, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn getTargetInfo(
|
fn getTargetInfo(
|
||||||
alloc: std.mem.Allocator,
|
alloc: std.mem.Allocator,
|
||||||
_id: ?u16,
|
msg: *IncomingMessage,
|
||||||
scanner: *std.json.Scanner,
|
|
||||||
_: *Ctx,
|
_: *Ctx,
|
||||||
) ![]const u8 {
|
) ![]const u8 {
|
||||||
|
|
||||||
// input
|
// input
|
||||||
const Params = struct {
|
const Params = struct {
|
||||||
targetId: ?[]const u8 = null,
|
targetId: ?[]const u8 = null,
|
||||||
};
|
};
|
||||||
const msg = try getMsg(alloc, _id, Params, scanner);
|
const input = try msg.getInput(alloc, Params);
|
||||||
log.debug("Req > id {d}, method {s}", .{ msg.id, "target.getTargetInfo" });
|
log.debug("Req > id {d}, method {s}", .{ input.id, "target.getTargetInfo" });
|
||||||
|
|
||||||
// output
|
// output
|
||||||
const TargetInfo = struct {
|
const TargetInfo = struct {
|
||||||
@@ -208,7 +200,7 @@ fn getTargetInfo(
|
|||||||
.targetId = BrowserTargetID,
|
.targetId = BrowserTargetID,
|
||||||
.type = "browser",
|
.type = "browser",
|
||||||
};
|
};
|
||||||
return result(alloc, msg.id, TargetInfo, targetInfo, null);
|
return result(alloc, input.id, TargetInfo, targetInfo, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Browser context are not handled and not in the roadmap for now
|
// Browser context are not handled and not in the roadmap for now
|
||||||
@@ -217,14 +209,12 @@ fn getTargetInfo(
|
|||||||
// TODO: noop method
|
// TODO: noop method
|
||||||
fn getBrowserContexts(
|
fn getBrowserContexts(
|
||||||
alloc: std.mem.Allocator,
|
alloc: std.mem.Allocator,
|
||||||
_id: ?u16,
|
msg: *IncomingMessage,
|
||||||
scanner: *std.json.Scanner,
|
|
||||||
ctx: *Ctx,
|
ctx: *Ctx,
|
||||||
) ![]const u8 {
|
) ![]const u8 {
|
||||||
|
|
||||||
// input
|
// input
|
||||||
const msg = try getMsg(alloc, _id, void, scanner);
|
const input = try msg.getInput(alloc, void);
|
||||||
log.debug("Req > id {d}, method {s}", .{ msg.id, "target.getBrowserContexts" });
|
log.debug("Req > id {d}, method {s}", .{ input.id, "target.getBrowserContexts" });
|
||||||
|
|
||||||
// ouptut
|
// ouptut
|
||||||
const Resp = struct {
|
const Resp = struct {
|
||||||
@@ -238,7 +228,7 @@ fn getBrowserContexts(
|
|||||||
const contextIDs = [0][]const u8{};
|
const contextIDs = [0][]const u8{};
|
||||||
resp = .{ .browserContextIds = &contextIDs };
|
resp = .{ .browserContextIds = &contextIDs };
|
||||||
}
|
}
|
||||||
return result(alloc, msg.id, Resp, resp, null);
|
return result(alloc, input.id, Resp, resp, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
const ContextID = "22648B09EDCCDD11109E2D4FEFBE4F89";
|
const ContextID = "22648B09EDCCDD11109E2D4FEFBE4F89";
|
||||||
@@ -246,11 +236,9 @@ const ContextID = "22648B09EDCCDD11109E2D4FEFBE4F89";
|
|||||||
// TODO: noop method
|
// TODO: noop method
|
||||||
fn createBrowserContext(
|
fn createBrowserContext(
|
||||||
alloc: std.mem.Allocator,
|
alloc: std.mem.Allocator,
|
||||||
_id: ?u16,
|
msg: *IncomingMessage,
|
||||||
scanner: *std.json.Scanner,
|
|
||||||
ctx: *Ctx,
|
ctx: *Ctx,
|
||||||
) ![]const u8 {
|
) ![]const u8 {
|
||||||
|
|
||||||
// input
|
// input
|
||||||
const Params = struct {
|
const Params = struct {
|
||||||
disposeOnDetach: bool = false,
|
disposeOnDetach: bool = false,
|
||||||
@@ -258,8 +246,8 @@ fn createBrowserContext(
|
|||||||
proxyBypassList: ?[]const u8 = null,
|
proxyBypassList: ?[]const u8 = null,
|
||||||
originsWithUniversalNetworkAccess: ?[][]const u8 = null,
|
originsWithUniversalNetworkAccess: ?[][]const u8 = null,
|
||||||
};
|
};
|
||||||
const msg = try getMsg(alloc, _id, Params, scanner);
|
const input = try msg.getInput(alloc, Params);
|
||||||
log.debug("Req > id {d}, method {s}", .{ msg.id, "target.createBrowserContext" });
|
log.debug("Req > id {d}, method {s}", .{ input.id, "target.createBrowserContext" });
|
||||||
|
|
||||||
ctx.state.contextID = ContextID;
|
ctx.state.contextID = ContextID;
|
||||||
|
|
||||||
@@ -279,25 +267,23 @@ fn createBrowserContext(
|
|||||||
try writer.writeAll(" }");
|
try writer.writeAll(" }");
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
return result(alloc, msg.id, Resp, Resp{}, msg.sessionID);
|
return result(alloc, input.id, Resp, Resp{}, input.sessionId);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn disposeBrowserContext(
|
fn disposeBrowserContext(
|
||||||
alloc: std.mem.Allocator,
|
alloc: std.mem.Allocator,
|
||||||
_id: ?u16,
|
msg: *IncomingMessage,
|
||||||
scanner: *std.json.Scanner,
|
|
||||||
ctx: *Ctx,
|
ctx: *Ctx,
|
||||||
) ![]const u8 {
|
) ![]const u8 {
|
||||||
|
|
||||||
// input
|
// input
|
||||||
const Params = struct {
|
const Params = struct {
|
||||||
browserContextId: []const u8,
|
browserContextId: []const u8,
|
||||||
};
|
};
|
||||||
const msg = try getMsg(alloc, _id, Params, scanner);
|
const input = try msg.getInput(alloc, Params);
|
||||||
log.debug("Req > id {d}, method {s}", .{ msg.id, "target.disposeBrowserContext" });
|
log.debug("Req > id {d}, method {s}", .{ input.id, "target.disposeBrowserContext" });
|
||||||
|
|
||||||
// output
|
// output
|
||||||
const res = try result(alloc, msg.id, null, .{}, null);
|
const res = try result(alloc, input.id, null, .{}, null);
|
||||||
try server.sendAsync(ctx, res);
|
try server.sendAsync(ctx, res);
|
||||||
|
|
||||||
return error.DisposeBrowserContext;
|
return error.DisposeBrowserContext;
|
||||||
@@ -309,11 +295,9 @@ const LoaderID = "DD4A76F842AA389647D702B4D805F49A";
|
|||||||
|
|
||||||
fn createTarget(
|
fn createTarget(
|
||||||
alloc: std.mem.Allocator,
|
alloc: std.mem.Allocator,
|
||||||
_id: ?u16,
|
msg: *IncomingMessage,
|
||||||
scanner: *std.json.Scanner,
|
|
||||||
ctx: *Ctx,
|
ctx: *Ctx,
|
||||||
) ![]const u8 {
|
) ![]const u8 {
|
||||||
|
|
||||||
// input
|
// input
|
||||||
const Params = struct {
|
const Params = struct {
|
||||||
url: []const u8,
|
url: []const u8,
|
||||||
@@ -325,8 +309,8 @@ fn createTarget(
|
|||||||
background: bool = false,
|
background: bool = false,
|
||||||
forTab: ?bool = null,
|
forTab: ?bool = null,
|
||||||
};
|
};
|
||||||
const msg = try getMsg(alloc, _id, Params, scanner);
|
const input = try msg.getInput(alloc, Params);
|
||||||
log.debug("Req > id {d}, method {s}", .{ msg.id, "target.createTarget" });
|
log.debug("Req > id {d}, method {s}", .{ input.id, "target.createTarget" });
|
||||||
|
|
||||||
// change CDP state
|
// change CDP state
|
||||||
ctx.state.frameID = TargetID;
|
ctx.state.frameID = TargetID;
|
||||||
@@ -346,7 +330,7 @@ fn createTarget(
|
|||||||
},
|
},
|
||||||
.waitingForDebugger = true,
|
.waitingForDebugger = true,
|
||||||
};
|
};
|
||||||
try cdp.sendEvent(alloc, ctx, "Target.attachedToTarget", AttachToTarget, attached, msg.sessionID);
|
try cdp.sendEvent(alloc, ctx, "Target.attachedToTarget", AttachToTarget, attached, input.sessionId);
|
||||||
|
|
||||||
// output
|
// output
|
||||||
const Resp = struct {
|
const Resp = struct {
|
||||||
@@ -364,28 +348,26 @@ fn createTarget(
|
|||||||
try writer.writeAll(" }");
|
try writer.writeAll(" }");
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
return result(alloc, msg.id, Resp, Resp{}, msg.sessionID);
|
return result(alloc, input.id, Resp, Resp{}, input.sessionId);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn closeTarget(
|
fn closeTarget(
|
||||||
alloc: std.mem.Allocator,
|
alloc: std.mem.Allocator,
|
||||||
_id: ?u16,
|
msg: *IncomingMessage,
|
||||||
scanner: *std.json.Scanner,
|
|
||||||
ctx: *Ctx,
|
ctx: *Ctx,
|
||||||
) ![]const u8 {
|
) ![]const u8 {
|
||||||
|
|
||||||
// input
|
// input
|
||||||
const Params = struct {
|
const Params = struct {
|
||||||
targetId: []const u8,
|
targetId: []const u8,
|
||||||
};
|
};
|
||||||
const msg = try getMsg(alloc, _id, Params, scanner);
|
const input = try msg.getInput(alloc, Params);
|
||||||
log.debug("Req > id {d}, method {s}", .{ msg.id, "target.closeTarget" });
|
log.debug("Req > id {d}, method {s}", .{ input.id, "target.closeTarget" });
|
||||||
|
|
||||||
// output
|
// output
|
||||||
const Resp = struct {
|
const Resp = struct {
|
||||||
success: bool = true,
|
success: bool = true,
|
||||||
};
|
};
|
||||||
const res = try result(alloc, msg.id, Resp, Resp{}, null);
|
const res = try result(alloc, input.id, Resp, Resp{}, null);
|
||||||
try server.sendAsync(ctx, res);
|
try server.sendAsync(ctx, res);
|
||||||
|
|
||||||
// Inspector.detached event
|
// Inspector.detached event
|
||||||
@@ -398,7 +380,7 @@ fn closeTarget(
|
|||||||
"Inspector.detached",
|
"Inspector.detached",
|
||||||
InspectorDetached,
|
InspectorDetached,
|
||||||
.{},
|
.{},
|
||||||
msg.sessionID orelse cdp.ContextSessionID,
|
input.sessionId orelse cdp.ContextSessionID,
|
||||||
);
|
);
|
||||||
|
|
||||||
// detachedFromTarget event
|
// detachedFromTarget event
|
||||||
@@ -412,8 +394,8 @@ fn closeTarget(
|
|||||||
"Target.detachedFromTarget",
|
"Target.detachedFromTarget",
|
||||||
TargetDetached,
|
TargetDetached,
|
||||||
.{
|
.{
|
||||||
.sessionId = msg.sessionID orelse cdp.ContextSessionID,
|
.sessionId = input.sessionId orelse cdp.ContextSessionID,
|
||||||
.targetId = msg.params.?.targetId,
|
.targetId = input.params.targetId,
|
||||||
},
|
},
|
||||||
null,
|
null,
|
||||||
);
|
);
|
||||||
|
|||||||
Reference in New Issue
Block a user