mirror of
https://github.com/lightpanda-io/browser.git
synced 2026-03-11 02:57:56 -04:00
The 'method' still needs to be the first or the second key (in this case after the 'id'). Signed-off-by: Francis Bouvier <francis@lightpanda.io>
174 lines
4.9 KiB
Zig
174 lines
4.9 KiB
Zig
const std = @import("std");
|
|
|
|
const jsruntime = @import("jsruntime");
|
|
|
|
const server = @import("../server.zig");
|
|
const Ctx = server.Cmd;
|
|
const cdp = @import("cdp.zig");
|
|
const result = cdp.result;
|
|
const getMsg = cdp.getMsg;
|
|
const stringify = cdp.stringify;
|
|
|
|
const RuntimeMethods = enum {
|
|
enable,
|
|
runIfWaitingForDebugger,
|
|
evaluate,
|
|
};
|
|
|
|
pub fn runtime(
|
|
alloc: std.mem.Allocator,
|
|
id: ?u16,
|
|
action: []const u8,
|
|
scanner: *std.json.Scanner,
|
|
ctx: *Ctx,
|
|
) ![]const u8 {
|
|
const method = std.meta.stringToEnum(RuntimeMethods, action) orelse
|
|
return error.UnknownMethod;
|
|
return switch (method) {
|
|
.enable => enable(alloc, id, scanner, ctx),
|
|
.runIfWaitingForDebugger => runIfWaitingForDebugger(alloc, id, scanner, ctx),
|
|
.evaluate => evaluate(alloc, id, scanner, ctx),
|
|
};
|
|
}
|
|
|
|
fn enable(
|
|
alloc: std.mem.Allocator,
|
|
id: ?u16,
|
|
scanner: *std.json.Scanner,
|
|
_: *Ctx,
|
|
) ![]const u8 {
|
|
|
|
// input
|
|
const msg = try getMsg(alloc, void, scanner);
|
|
|
|
// output
|
|
// const uniqueID = "1367118932354479079.-1471398151593995849";
|
|
// const mainCtx = try executionContextCreated(
|
|
// alloc,
|
|
// 1,
|
|
// cdp.URLBase,
|
|
// "",
|
|
// uniqueID,
|
|
// .{},
|
|
// sessionID,
|
|
// );
|
|
// std.log.debug("res {s}", .{mainCtx});
|
|
// try server.sendAsync(ctx, mainCtx);
|
|
|
|
return result(alloc, id orelse msg.id.?, null, null, msg.sessionID);
|
|
}
|
|
|
|
pub const AuxData = struct {
|
|
isDefault: bool = true,
|
|
type: []const u8 = "default",
|
|
frameId: []const u8 = cdp.FrameID,
|
|
};
|
|
|
|
const ExecutionContextDescription = struct {
|
|
id: u64,
|
|
origin: []const u8,
|
|
name: []const u8,
|
|
uniqueId: []const u8,
|
|
auxData: ?AuxData = null,
|
|
};
|
|
|
|
pub fn executionContextCreated(
|
|
alloc: std.mem.Allocator,
|
|
ctx: *Ctx,
|
|
id: u16,
|
|
origin: []const u8,
|
|
name: []const u8,
|
|
uniqueID: []const u8,
|
|
auxData: ?AuxData,
|
|
sessionID: ?[]const u8,
|
|
) !void {
|
|
const Params = struct {
|
|
context: ExecutionContextDescription,
|
|
};
|
|
const params = Params{
|
|
.context = .{
|
|
.id = id,
|
|
.origin = origin,
|
|
.name = name,
|
|
.uniqueId = uniqueID,
|
|
.auxData = auxData,
|
|
},
|
|
};
|
|
try cdp.sendEvent(alloc, ctx, "Runtime.executionContextCreated", Params, params, sessionID);
|
|
}
|
|
|
|
fn runIfWaitingForDebugger(
|
|
alloc: std.mem.Allocator,
|
|
id: ?u16,
|
|
scanner: *std.json.Scanner,
|
|
_: *Ctx,
|
|
) ![]const u8 {
|
|
const msg = try getMsg(alloc, void, scanner);
|
|
|
|
return result(alloc, id orelse msg.id.?, null, null, msg.sessionID);
|
|
}
|
|
|
|
fn evaluate(
|
|
alloc: std.mem.Allocator,
|
|
_id: ?u16,
|
|
scanner: *std.json.Scanner,
|
|
ctx: *Ctx,
|
|
) ![]const u8 {
|
|
|
|
// ensure a page has been previously created
|
|
if (ctx.browser.currentSession().page == null) return error.CDPNoPage;
|
|
|
|
// input
|
|
const Params = struct {
|
|
expression: []const u8,
|
|
contextId: ?u8,
|
|
};
|
|
|
|
const msg = try getMsg(alloc, Params, scanner);
|
|
std.debug.assert(msg.sessionID != null);
|
|
const params = msg.params.?;
|
|
const id = _id orelse msg.id.?;
|
|
|
|
// save script in file at debug mode
|
|
std.log.debug("script {d} length: {d}", .{ id, params.expression.len });
|
|
if (std.log.defaultLogEnabled(.debug)) {
|
|
const name = try std.fmt.allocPrint(alloc, "id_{d}.js", .{id});
|
|
defer alloc.free(name);
|
|
const dir = try std.fs.cwd().makeOpenPath("zig-cache/tmp", .{});
|
|
const f = try dir.createFile(name, .{});
|
|
defer f.close();
|
|
const nb = try f.write(params.expression);
|
|
std.debug.assert(nb == params.expression.len);
|
|
const p = try dir.realpathAlloc(alloc, name);
|
|
defer alloc.free(p);
|
|
std.log.debug("Script {d} saved at {s}", .{ id, p });
|
|
}
|
|
|
|
// evaluate the script in the context of the current page
|
|
// TODO: should we use instead the allocator of the page?
|
|
// the following code does not work
|
|
// const page_alloc = ctx.browser.currentSession().page.?.arena.allocator();
|
|
const session_alloc = ctx.browser.currentSession().alloc;
|
|
var res = jsruntime.JSResult{};
|
|
try ctx.browser.currentSession().env.run(session_alloc, params.expression, "cdp", &res, null);
|
|
defer res.deinit(session_alloc);
|
|
|
|
if (!res.success) {
|
|
std.log.err("script {d} result: {s}", .{ id, res.result });
|
|
if (res.stack) |stack| {
|
|
std.log.err("script {d} stack: {s}", .{ id, stack });
|
|
}
|
|
return error.CDPRuntimeEvaluate;
|
|
}
|
|
std.log.debug("script {d} result: {s}", .{ id, res.result });
|
|
|
|
// TODO: Resp should depends on JS result returned by the JS engine
|
|
const Resp = struct {
|
|
type: []const u8 = "object",
|
|
className: []const u8 = "UtilityScript",
|
|
description: []const u8 = "UtilityScript",
|
|
objectId: []const u8 = "7481631759780215274.3.2",
|
|
};
|
|
return result(alloc, id, Resp, Resp{}, msg.sessionID);
|
|
}
|