From d664d0714174a73f88ab50cff14777a5e406798a Mon Sep 17 00:00:00 2001 From: Pierre Tachoire Date: Fri, 25 Oct 2024 18:28:32 +0200 Subject: [PATCH 1/9] cdp: dispatch executionContextCreated on Runtime.enable --- src/cdp/runtime.zig | 21 +++++++++++++++++++++ src/cdp/target.zig | 6 +++--- 2 files changed, 24 insertions(+), 3 deletions(-) diff --git a/src/cdp/runtime.zig b/src/cdp/runtime.zig index 3eef3f6c..2cda8e74 100644 --- a/src/cdp/runtime.zig +++ b/src/cdp/runtime.zig @@ -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); @@ -130,6 +131,26 @@ fn sendInspector( ctx.sendInspector(msg.json); + if (method == .enable) { + try executionContextCreated( + alloc, + ctx, + 0, + "://", + "", + // TODO: hard coded ID + "7102379147004877974.3265385113993241162", + .{ + .isDefault = true, + .type = "default", + // TODO: hard coded ID + .frameId = cdp.FrameID, + }, + // TODO: hard coded ID + target.BrowserContextID, + ); + } + if (msg.id == null) return ""; return result(alloc, msg.id.?, null, null, msg.sessionId); diff --git a/src/cdp/target.zig b/src/cdp/target.zig index d21b4edd..3a11a8ca 100644 --- a/src/cdp/target.zig +++ b/src/cdp/target.zig @@ -64,9 +64,9 @@ pub fn target( } // TODO: hard coded IDs -const PageTargetID = "CFCD6EC01573CF29BB638E9DC0F52DDC"; -const BrowserTargetID = "2d2bdef9-1c95-416f-8c0e-83f3ab73a30c"; -const BrowserContextID = "65618675CB7D3585A95049E9DFE95EA9"; +pub const PageTargetID = "CFCD6EC01573CF29BB638E9DC0F52DDC"; +pub const BrowserTargetID = "2d2bdef9-1c95-416f-8c0e-83f3ab73a30c"; +pub const BrowserContextID = "65618675CB7D3585A95049E9DFE95EA9"; // TODO: noop method fn setDiscoverTargets( From bcaace1c9198b31b4922642f12b0d42294171004 Mon Sep 17 00:00:00 2001 From: Pierre Tachoire Date: Mon, 28 Oct 2024 11:58:02 +0100 Subject: [PATCH 2/9] cdp: use identifiable hard coded ids --- src/cdp/cdp.zig | 8 ++++---- src/cdp/target.zig | 12 ++++++------ 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/cdp/cdp.zig b/src/cdp/cdp.zig index 95174a2d..c186765e 100644 --- a/src/cdp/cdp.zig +++ b/src/cdp/cdp.zig @@ -221,11 +221,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, diff --git a/src/cdp/target.zig b/src/cdp/target.zig index 3a11a8ca..4a367cac 100644 --- a/src/cdp/target.zig +++ b/src/cdp/target.zig @@ -64,9 +64,9 @@ pub fn target( } // TODO: hard coded IDs -pub const PageTargetID = "CFCD6EC01573CF29BB638E9DC0F52DDC"; -pub const BrowserTargetID = "2d2bdef9-1c95-416f-8c0e-83f3ab73a30c"; -pub const BrowserContextID = "65618675CB7D3585A95049E9DFE95EA9"; +pub const PageTargetID = "PAGETARGETIDB638E9DC0F52DDC"; +pub const BrowserTargetID = "browser9-targ-et6f-id0e-83f3ab73a30c"; +pub const BrowserContextID = "BROWSERCONTEXTIDA95049E9DFE95EA9"; // TODO: noop method fn setDiscoverTargets( @@ -252,7 +252,7 @@ fn getBrowserContexts( return result(alloc, input.id, Resp, resp, null); } -const ContextID = "22648B09EDCCDD11109E2D4FEFBE4F89"; +const ContextID = "CONTEXTIDDCCDD11109E2D4FEFBE4F89"; // TODO: noop method fn createBrowserContext( @@ -313,8 +313,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, From 8e2cb3659778736c5e7e2d750162bf7efad83038 Mon Sep 17 00:00:00 2001 From: Pierre Tachoire Date: Wed, 18 Dec 2024 16:54:01 +0100 Subject: [PATCH 3/9] cdp: fix some id inconsitency accross runtime messages --- src/cdp/cdp.zig | 1 + src/cdp/runtime.zig | 8 ++++---- src/cdp/target.zig | 12 +++++++----- src/server.zig | 2 +- 4 files changed, 13 insertions(+), 10 deletions(-) diff --git a/src/cdp/cdp.zig b/src/cdp/cdp.zig index c186765e..5c056763 100644 --- a/src/cdp/cdp.zig +++ b/src/cdp/cdp.zig @@ -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, diff --git a/src/cdp/runtime.zig b/src/cdp/runtime.zig index 2cda8e74..ffdbb438 100644 --- a/src/cdp/runtime.zig +++ b/src/cdp/runtime.zig @@ -129,13 +129,11 @@ fn sendInspector( } } - ctx.sendInspector(msg.json); - if (method == .enable) { try executionContextCreated( alloc, ctx, - 0, + 1, "://", "", // TODO: hard coded ID @@ -147,10 +145,12 @@ fn sendInspector( .frameId = cdp.FrameID, }, // TODO: hard coded ID - target.BrowserContextID, + msg.sessionId orelse target.BrowserContextID, ); } + ctx.sendInspector(msg.json); + if (msg.id == null) return ""; return result(alloc, msg.id.?, null, null, msg.sessionId); diff --git a/src/cdp/target.zig b/src/cdp/target.zig index 4a367cac..6d3c611b 100644 --- a/src/cdp/target.zig +++ b/src/cdp/target.zig @@ -138,7 +138,7 @@ fn setAutoAttach( .sessionId = cdp.BrowserSessionID, .targetInfo = .{ .targetId = PageTargetID, - .title = "New Incognito tab", + .title = "about:blank", .url = cdp.URLBase, .browserContextId = BrowserContextID, }, @@ -171,8 +171,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, }, @@ -185,7 +185,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); } @@ -342,6 +342,7 @@ fn createTarget( ctx.state.securityOrigin = "://"; ctx.state.secureContextType = "InsecureScheme"; ctx.state.loaderID = LoaderID; + ctx.state.sessionID = msg.sessionId; // send targetCreated event const created = TargetCreated{ @@ -361,9 +362,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, }; diff --git a/src/server.zig b/src/server.zig index 5e83c009..89626c2e 100644 --- a/src/server.zig +++ b/src/server.zig @@ -347,7 +347,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); From 2fed239ece4eadaeee80fc8ac176e2d0e06a75a5 Mon Sep 17 00:00:00 2001 From: Pierre Tachoire Date: Thu, 19 Dec 2024 10:00:49 +0100 Subject: [PATCH 4/9] browser: split page start from page navigate --- src/browser/browser.zig | 26 ++++++++++++++------------ src/cdp/page.zig | 5 +++-- src/cdp/target.zig | 10 ++++++++++ src/main.zig | 2 ++ 4 files changed, 29 insertions(+), 14 deletions(-) diff --git a/src/browser/browser.zig b/src/browser/browser.zig index 635390c4..cc153870 100644 --- a/src/browser/browser.zig +++ b/src/browser/browser.zig @@ -214,6 +214,20 @@ pub const Page = struct { }; } + // start js env. + pub fn start(self: *Page) !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); + } + // reset js env and mem arena. pub fn end(self: *Page) void { self.session.env.stop(); @@ -373,14 +387,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); @@ -395,10 +401,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 diff --git a/src/cdp/page.zig b/src/cdp/page.zig index cf86297f..d453e9d5 100644 --- a/src/cdp/page.zig +++ b/src/cdp/page.zig @@ -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, diff --git a/src/cdp/target.zig b/src/cdp/target.zig index 6d3c611b..048c1d68 100644 --- a/src/cdp/target.zig +++ b/src/cdp/target.zig @@ -344,6 +344,14 @@ fn createTarget( 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(); + // start the js env + try p.start(); + // send targetCreated event const created = TargetCreated{ .sessionId = cdp.ContextSessionID, @@ -440,6 +448,8 @@ fn closeTarget( null, ); + if (ctx.browser.session.page != null) ctx.browser.session.page.?.end(); + return ""; } diff --git a/src/main.zig b/src/main.zig index 84e23536..787f1501 100644 --- a/src/main.zig +++ b/src/main.zig @@ -326,6 +326,8 @@ pub fn main() !void { // page const page = try browser.session.createPage(); + try page.start(); + defer page.end(); _ = page.navigate(opts.url, null) catch |err| switch (err) { error.UnsupportedUriScheme, error.UriMissingHost => { From b276a157866d8e4e5df319e9bc72fa19226a36d0 Mon Sep 17 00:00:00 2001 From: Pierre Tachoire Date: Thu, 19 Dec 2024 14:15:29 +0100 Subject: [PATCH 5/9] cdp: add target.detachFromTarget noop --- src/cdp/target.zig | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/src/cdp/target.zig b/src/cdp/target.zig index 048c1d68..ea8aac87 100644 --- a/src/cdp/target.zig +++ b/src/cdp/target.zig @@ -39,6 +39,7 @@ const Methods = enum { createTarget, closeTarget, sendMessageToTarget, + detachFromTarget, }; pub fn target( @@ -60,6 +61,7 @@ pub fn target( .createTarget => createTarget(alloc, msg, ctx), .closeTarget => closeTarget(alloc, msg, ctx), .sendMessageToTarget => sendMessageToTarget(alloc, msg, ctx), + .detachFromTarget => detachFromTarget(alloc, msg, ctx), }; } @@ -496,3 +498,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); +} From c5688c1bd32a8bf563eebdcb001526cd6684debe Mon Sep 17 00:00:00 2001 From: Pierre Tachoire Date: Thu, 19 Dec 2024 14:16:27 +0100 Subject: [PATCH 6/9] cdp: display last message on cdp error --- src/server.zig | 1 + 1 file changed, 1 insertion(+) diff --git a/src/server.zig b/src/server.zig index 89626c2e..df25f4f6 100644 --- a/src/server.zig +++ b/src/server.zig @@ -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}); } }; } From c149f651586b0dbe58e85370ecc9fc8f3cc3bd9d Mon Sep 17 00:00:00 2001 From: Pierre Tachoire Date: Sun, 29 Dec 2024 10:22:20 +0100 Subject: [PATCH 7/9] cdp: remove event dispateched by inspector --- src/cdp/runtime.zig | 20 -------------------- 1 file changed, 20 deletions(-) diff --git a/src/cdp/runtime.zig b/src/cdp/runtime.zig index ffdbb438..7dfdcd84 100644 --- a/src/cdp/runtime.zig +++ b/src/cdp/runtime.zig @@ -129,26 +129,6 @@ fn sendInspector( } } - if (method == .enable) { - try executionContextCreated( - alloc, - ctx, - 1, - "://", - "", - // TODO: hard coded ID - "7102379147004877974.3265385113993241162", - .{ - .isDefault = true, - .type = "default", - // TODO: hard coded ID - .frameId = cdp.FrameID, - }, - // TODO: hard coded ID - msg.sessionId orelse target.BrowserContextID, - ); - } - ctx.sendInspector(msg.json); if (msg.id == null) return ""; From 4c9a24c64ee3721b7e2cf4886e8727dd04dd4070 Mon Sep 17 00:00:00 2001 From: Pierre Tachoire Date: Sun, 29 Dec 2024 10:22:46 +0100 Subject: [PATCH 8/9] start inspector when the js env starts --- src/browser/browser.zig | 16 ++++++++++++---- src/cdp/target.zig | 10 +++++++++- src/main.zig | 2 +- 3 files changed, 22 insertions(+), 6 deletions(-) diff --git a/src/browser/browser.zig b/src/browser/browser.zig index cc153870..c421498c 100644 --- a/src/browser/browser.zig +++ b/src/browser/browser.zig @@ -215,7 +215,9 @@ pub const Page = struct { } // start js env. - pub fn start(self: *Page) !void { + // - 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(); @@ -226,6 +228,15 @@ pub const Page = struct { // 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. @@ -387,9 +398,6 @@ pub const Page = struct { // https://html.spec.whatwg.org/#read-html - // load polyfills - try polyfill.load(alloc, self.session.env); - // inspector if (self.session.inspector) |inspector| { inspector.contextCreated(self.session.env, "", self.origin.?, auxData); diff --git a/src/cdp/target.zig b/src/cdp/target.zig index ea8aac87..e3120379 100644 --- a/src/cdp/target.zig +++ b/src/cdp/target.zig @@ -351,8 +351,16 @@ fn createTarget( // create the page const p = try ctx.browser.session.createPage(); + ctx.state.executionContextId += 1; // start the js env - try p.start(); + 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{ diff --git a/src/main.zig b/src/main.zig index 787f1501..e4da1df2 100644 --- a/src/main.zig +++ b/src/main.zig @@ -326,7 +326,7 @@ pub fn main() !void { // page const page = try browser.session.createPage(); - try page.start(); + try page.start(null); defer page.end(); _ = page.navigate(opts.url, null) catch |err| switch (err) { From daf42360234233493df24340410c9dffd4a3f895 Mon Sep 17 00:00:00 2001 From: Pierre Tachoire Date: Mon, 13 Jan 2025 18:08:09 +0100 Subject: [PATCH 9/9] runtime: fix sessionid --- src/cdp/runtime.zig | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/cdp/runtime.zig b/src/cdp/runtime.zig index 7dfdcd84..f0c58b53 100644 --- a/src/cdp/runtime.zig +++ b/src/cdp/runtime.zig @@ -117,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) {