diff --git a/src/browser/page.zig b/src/browser/page.zig index 897cb414..ddd5fc89 100644 --- a/src/browser/page.zig +++ b/src/browser/page.zig @@ -549,14 +549,31 @@ pub const Page = struct { .body = opts.body != null, }); - // if the url is about:blank, nothing to do. + // if the url is about:blank, we load an empty HTML document in the + // page and dispatch the events. if (std.mem.eql(u8, "about:blank", request_url)) { const html_doc = try parser.documentHTMLParseFromStr(""); try self.setDocument(html_doc); + // Assume we parsed the document. + // It's important to force a reset during the following navigation. + self.mode = .parsed; + // We do not processHTMLDoc here as we know we don't have any scripts // This assumption may be false when CDP Page.addScriptToEvaluateOnNewDocument is implemented - try HTMLDocument.documentIsComplete(self.window.document, self); + self.documentIsComplete(); + + self.session.browser.notification.dispatch(.page_navigate, &.{ + .opts = opts, + .url = request_url, + .timestamp = timestamp(), + }); + + self.session.browser.notification.dispatch(.page_navigated, &.{ + .url = request_url, + .timestamp = timestamp(), + }); + return; } diff --git a/src/cdp/domains/page.zig b/src/cdp/domains/page.zig index 1f6b720a..91656103 100644 --- a/src/cdp/domains/page.zig +++ b/src/cdp/domains/page.zig @@ -18,6 +18,7 @@ const std = @import("std"); const Page = @import("../../browser/page.zig").Page; +const timestampF = @import("../../datetime.zig").timestamp; const Notification = @import("../../notification.zig").Notification; const Allocator = std.mem.Allocator; @@ -82,11 +83,33 @@ fn setLifecycleEventsEnabled(cmd: anytype) !void { })) orelse return error.InvalidParams; const bc = cmd.browser_context orelse return error.BrowserContextNotLoaded; - if (params.enabled) { - try bc.lifecycleEventsEnable(); - } else { + + if (params.enabled == false) { bc.lifecycleEventsDisable(); + return cmd.sendResult(null, .{}); } + + // Enable lifecycle events. + try bc.lifecycleEventsEnable(); + + // When we enable lifecycle events, we must dispatch events for all + // attached targets. + const page = bc.session.currentPage() orelse return error.PageNotLoaded; + + if (page.load_state == .complete) { + try sendPageLifecycle(bc, "DOMContentLoaded", timestampF()); + try sendPageLifecycle(bc, "load", timestampF()); + + const http_active = page.http_client.active; + const total_network_activity = http_active + page.http_client.intercepted; + if (page.notified_network_almost_idle.check(total_network_activity <= 2)) { + try sendPageLifecycle(bc, "networkAlmostIdle", timestampF()); + } + if (page.notified_network_idle.check(total_network_activity == 0)) { + try sendPageLifecycle(bc, "networkIdle", timestampF()); + } + } + return cmd.sendResult(null, .{}); } diff --git a/src/cdp/domains/target.zig b/src/cdp/domains/target.zig index 26f4cfbe..2d7c3b02 100644 --- a/src/cdp/domains/target.zig +++ b/src/cdp/domains/target.zig @@ -109,7 +109,7 @@ fn disposeBrowserContext(cmd: anytype) !void { fn createTarget(cmd: anytype) !void { const params = (try cmd.params(struct { - // url: []const u8, + url: []const u8 = "about:blank", // width: ?u64 = null, // height: ?u64 = null, browserContextId: ?[]const u8 = null, @@ -167,7 +167,7 @@ fn createTarget(cmd: anytype) !void { .targetInfo = TargetInfo{ .attached = false, .targetId = target_id, - .title = "about:blank", + .title = params.url, .browserContextId = bc.id, .url = "about:blank", }, @@ -178,6 +178,10 @@ fn createTarget(cmd: anytype) !void { try doAttachtoTarget(cmd, target_id); } + try page.navigate(params.url, .{ + .reason = .address_bar, + }); + try cmd.sendResult(.{ .targetId = target_id, }, .{}); @@ -517,7 +521,7 @@ test "cdp.target: createTarget" { { var ctx = testing.context(); defer ctx.deinit(); - try ctx.processMessage(.{ .id = 10, .method = "Target.createTarget", .params = .{ .url = "about/blank" } }); + try ctx.processMessage(.{ .id = 10, .method = "Target.createTarget", .params = .{ .url = "about:blank" } }); // should create a browser context const bc = ctx.cdp().browser_context.?; @@ -529,7 +533,7 @@ test "cdp.target: createTarget" { defer ctx.deinit(); // active auto attach to get the Target.attachedToTarget event. try ctx.processMessage(.{ .id = 9, .method = "Target.setAutoAttach", .params = .{ .autoAttach = true, .waitForDebuggerOnStart = false } }); - try ctx.processMessage(.{ .id = 10, .method = "Target.createTarget", .params = .{ .url = "about/blank" } }); + try ctx.processMessage(.{ .id = 10, .method = "Target.createTarget", .params = .{ .url = "about:blank" } }); // should create a browser context const bc = ctx.cdp().browser_context.?; diff --git a/src/http/Client.zig b/src/http/Client.zig index 40647336..588e0c4f 100644 --- a/src/http/Client.zig +++ b/src/http/Client.zig @@ -338,8 +338,6 @@ pub fn restoreOriginalProxy(self: *Client) !void { // Enable TLS verification on all connections. pub fn enableTlsVerify(self: *const Client) !void { - try self.ensureNoActiveConnection(); - for (self.handles.handles) |*h| { const easy = h.conn.easy; @@ -355,8 +353,6 @@ pub fn enableTlsVerify(self: *const Client) !void { // Disable TLS verification on all connections. pub fn disableTlsVerify(self: *const Client) !void { - try self.ensureNoActiveConnection(); - for (self.handles.handles) |*h| { const easy = h.conn.easy;