Skip to content

Commit

Permalink
Merge pull request #285 from lightpanda-io/cdp-cdpcli
Browse files Browse the repository at this point in the history
cdp: cdpcli compatibility
  • Loading branch information
krichprollsch authored Jan 13, 2025
2 parents cb8b80c + daf4236 commit 73bb14e
Show file tree
Hide file tree
Showing 7 changed files with 88 additions and 33 deletions.
40 changes: 25 additions & 15 deletions src/browser/browser.zig
Original file line number Diff line number Diff line change
Expand Up @@ -214,6 +214,31 @@ pub const Page = struct {
};
}

// start js env.
// - auxData: extra data forwarded to the Inspector
// see Inspector.contextCreated
pub fn start(self: *Page, auxData: ?[]const u8) !void {
// start JS env
log.debug("start js env", .{});
try self.session.env.start();

// register the module loader
try self.session.env.setModuleLoadFn(self.session, Session.fetchModule);

// add global objects
log.debug("setup global env", .{});
try self.session.env.bindGlobal(&self.session.window);

// load polyfills
try polyfill.load(self.arena.allocator(), self.session.env);

// inspector
if (self.session.inspector) |inspector| {
log.debug("inspector context created", .{});
inspector.contextCreated(self.session.env, "", self.origin orelse "://", auxData);
}
}

// reset js env and mem arena.
pub fn end(self: *Page) void {
self.session.env.stop();
Expand Down Expand Up @@ -373,17 +398,6 @@ pub const Page = struct {

// https://html.spec.whatwg.org/#read-html

// start JS env
// TODO load the js env concurrently with the HTML parsing.
log.debug("start js env", .{});
try self.session.env.start();

// register the module loader
try self.session.env.setModuleLoadFn(self.session, Session.fetchModule);

// load polyfills
try polyfill.load(alloc, self.session.env);

// inspector
if (self.session.inspector) |inspector| {
inspector.contextCreated(self.session.env, "", self.origin.?, auxData);
Expand All @@ -395,10 +409,6 @@ pub const Page = struct {
.httpClient = &self.session.httpClient,
});

// add global objects
log.debug("setup global env", .{});
try self.session.env.bindGlobal(&self.session.window);

// browse the DOM tree to retrieve scripts
// TODO execute the synchronous scripts during the HTL parsing.
// TODO fetch the script resources concurrently but execute them in the
Expand Down
9 changes: 5 additions & 4 deletions src/cdp/cdp.zig
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,7 @@ pub fn dispatch(
pub const State = struct {
executionContextId: u32 = 0,
contextID: ?[]const u8 = null,
sessionID: ?[]const u8 = null,
frameID: []const u8 = FrameID,
url: []const u8 = URLBase,
securityOrigin: []const u8 = URLBase,
Expand Down Expand Up @@ -221,11 +222,11 @@ pub fn sendEvent(
// ------

// TODO: hard coded IDs
pub const BrowserSessionID = "9559320D92474062597D9875C664CAC0";
pub const ContextSessionID = "4FDC2CB760A23A220497A05C95417CF4";
pub const BrowserSessionID = "BROWSERSESSIONID597D9875C664CAC0";
pub const ContextSessionID = "CONTEXTSESSIONID0497A05C95417CF4";
pub const URLBase = "chrome://newtab/";
pub const FrameID = "90D14BBD8AED408A0467AC93100BCDBE";
pub const LoaderID = "CFC8BED824DD2FD56CF1EF33C965C79C";
pub const LoaderID = "LOADERID24DD2FD56CF1EF33C965C79C";
pub const FrameID = "FRAMEIDD8AED408A0467AC93100BCDBE";

pub const TimestampEvent = struct {
timestamp: f64,
Expand Down
5 changes: 3 additions & 2 deletions src/cdp/page.zig
Original file line number Diff line number Diff line change
Expand Up @@ -331,8 +331,9 @@ fn navigate(
// TODO: noop event, we have no env context at this point, is it necesarry?
try sendEvent(alloc, ctx, "Runtime.executionContextsCleared", void, {}, input.sessionId);

// Launch navigate
const p = try ctx.browser.session.createPage();
// Launch navigate, the page must have been created by a
// target.createTarget.
var p = ctx.browser.session.page orelse return error.NoPage;
ctx.state.executionContextId += 1;
const auxData = try std.fmt.allocPrint(
alloc,
Expand Down
3 changes: 3 additions & 0 deletions src/cdp/runtime.zig
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ const result = cdp.result;
const IncomingMessage = @import("msg.zig").IncomingMessage;
const Input = @import("msg.zig").Input;
const stringify = cdp.stringify;
const target = @import("target.zig");

const log = std.log.scoped(.cdp);

Expand Down Expand Up @@ -116,6 +117,8 @@ fn sendInspector(
}
}

ctx.state.sessionID = msg.sessionId;

// remove awaitPromise true params
// TODO: delete when Promise are correctly handled by zig-js-runtime
if (method == .callFunctionOn or method == .evaluate) {
Expand Down
59 changes: 48 additions & 11 deletions src/cdp/target.zig
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ const Methods = enum {
createTarget,
closeTarget,
sendMessageToTarget,
detachFromTarget,
};

pub fn target(
Expand All @@ -60,13 +61,14 @@ pub fn target(
.createTarget => createTarget(alloc, msg, ctx),
.closeTarget => closeTarget(alloc, msg, ctx),
.sendMessageToTarget => sendMessageToTarget(alloc, msg, ctx),
.detachFromTarget => detachFromTarget(alloc, msg, ctx),
};
}

// TODO: hard coded IDs
const PageTargetID = "CFCD6EC01573CF29BB638E9DC0F52DDC";
const BrowserTargetID = "2d2bdef9-1c95-416f-8c0e-83f3ab73a30c";
const BrowserContextID = "65618675CB7D3585A95049E9DFE95EA9";
pub const PageTargetID = "PAGETARGETIDB638E9DC0F52DDC";
pub const BrowserTargetID = "browser9-targ-et6f-id0e-83f3ab73a30c";
pub const BrowserContextID = "BROWSERCONTEXTIDA95049E9DFE95EA9";

// TODO: noop method
fn setDiscoverTargets(
Expand Down Expand Up @@ -138,7 +140,7 @@ fn setAutoAttach(
.sessionId = cdp.BrowserSessionID,
.targetInfo = .{
.targetId = PageTargetID,
.title = "New Incognito tab",
.title = "about:blank",
.url = cdp.URLBase,
.browserContextId = BrowserContextID,
},
Expand Down Expand Up @@ -171,8 +173,8 @@ fn attachToTarget(
const attached = AttachToTarget{
.sessionId = cdp.BrowserSessionID,
.targetInfo = .{
.targetId = PageTargetID,
.title = "New Incognito tab",
.targetId = input.params.targetId,
.title = "about:blank",
.url = cdp.URLBase,
.browserContextId = BrowserContextID,
},
Expand All @@ -185,7 +187,7 @@ fn attachToTarget(
sessionId: []const u8,
};
const output = SessionId{
.sessionId = input.sessionId orelse BrowserContextID,
.sessionId = input.sessionId orelse cdp.BrowserSessionID,
};
return result(alloc, input.id, SessionId, output, null);
}
Expand Down Expand Up @@ -252,7 +254,7 @@ fn getBrowserContexts(
return result(alloc, input.id, Resp, resp, null);
}

const ContextID = "22648B09EDCCDD11109E2D4FEFBE4F89";
const ContextID = "CONTEXTIDDCCDD11109E2D4FEFBE4F89";

// TODO: noop method
fn createBrowserContext(
Expand Down Expand Up @@ -313,8 +315,8 @@ fn disposeBrowserContext(
}

// TODO: hard coded IDs
const TargetID = "57356548460A8F29706A2ADF14316298";
const LoaderID = "DD4A76F842AA389647D702B4D805F49A";
const TargetID = "TARGETID460A8F29706A2ADF14316298";
const LoaderID = "LOADERID42AA389647D702B4D805F49A";

fn createTarget(
alloc: std.mem.Allocator,
Expand Down Expand Up @@ -342,6 +344,23 @@ fn createTarget(
ctx.state.securityOrigin = "://";
ctx.state.secureContextType = "InsecureScheme";
ctx.state.loaderID = LoaderID;
ctx.state.sessionID = msg.sessionId;

// TODO stop the previous page instead?
if (ctx.browser.session.page != null) return error.pageAlreadyExists;

// create the page
const p = try ctx.browser.session.createPage();
ctx.state.executionContextId += 1;
// start the js env
const auxData = try std.fmt.allocPrint(
alloc,
// NOTE: we assume this is the default web page
"{{\"isDefault\":true,\"type\":\"default\",\"frameId\":\"{s}\"}}",
.{ctx.state.frameID},
);
defer alloc.free(auxData);
try p.start(auxData);

// send targetCreated event
const created = TargetCreated{
Expand All @@ -361,9 +380,10 @@ fn createTarget(
.sessionId = cdp.ContextSessionID,
.targetInfo = .{
.targetId = ctx.state.frameID,
.title = "",
.title = "about:blank",
.url = ctx.state.url,
.browserContextId = input.params.browserContextId orelse ContextID,
.attached = true,
},
.waitingForDebugger = true,
};
Expand Down Expand Up @@ -438,6 +458,8 @@ fn closeTarget(
null,
);

if (ctx.browser.session.page != null) ctx.browser.session.page.?.end();

return "";
}

Expand Down Expand Up @@ -484,3 +506,18 @@ fn sendMessageToTarget(

return "";
}

// noop
fn detachFromTarget(
alloc: std.mem.Allocator,
msg: *IncomingMessage,
_: *Ctx,
) ![]const u8 {
// input
const input = try Input(void).get(alloc, msg);
defer input.deinit();
log.debug("Req > id {d}, method {s}", .{ input.id, "target.detachFromTarget" });

// output
return result(alloc, input.id, bool, true, input.sessionId);
}
2 changes: 2 additions & 0 deletions src/main.zig
Original file line number Diff line number Diff line change
Expand Up @@ -326,6 +326,8 @@ pub fn main() !void {

// page
const page = try browser.session.createPage();
try page.start(null);
defer page.end();

_ = page.navigate(opts.url, null) catch |err| switch (err) {
error.UnsupportedUriScheme, error.UriMissingHost => {
Expand Down
3 changes: 2 additions & 1 deletion src/server.zig
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,7 @@ pub const Ctx = struct {
self.do(parts.msg) catch |err| {
if (err != error.Closed) {
log.err("do error: {any}", .{err});
log.debug("last msg: {s}", .{parts.msg});
}
};
}
Expand Down Expand Up @@ -347,7 +348,7 @@ pub const Ctx = struct {
const s = try std.fmt.allocPrint(
allocator,
tpl,
.{ msg_open, cdp.ContextSessionID },
.{ msg_open, ctx.state.sessionID orelse cdp.ContextSessionID },
);

try ctx.send(s);
Expand Down

0 comments on commit 73bb14e

Please sign in to comment.