mirror of
https://github.com/lightpanda-io/browser.git
synced 2026-06-11 01:25:53 -04:00
Merge pull request #2085 from tmchow/feat/2082-handle-javascript-dialog
feat: emit Page.javascriptDialogOpening CDP events for JS dialogs
This commit is contained in:
@@ -83,6 +83,7 @@ const EventListeners = struct {
|
||||
http_request_auth_required: List = .{},
|
||||
http_response_data: List = .{},
|
||||
http_response_header_done: List = .{},
|
||||
javascript_dialog_opening: List = .{},
|
||||
};
|
||||
|
||||
const Events = union(enum) {
|
||||
@@ -102,6 +103,7 @@ const Events = union(enum) {
|
||||
http_request_done: *const RequestDone,
|
||||
http_response_data: *const ResponseData,
|
||||
http_response_header_done: *const ResponseHeaderDone,
|
||||
javascript_dialog_opening: *const JavascriptDialogOpening,
|
||||
};
|
||||
const EventType = std.meta.FieldEnum(Events);
|
||||
|
||||
@@ -185,6 +187,12 @@ pub const RequestFail = struct {
|
||||
err: anyerror,
|
||||
};
|
||||
|
||||
pub const JavascriptDialogOpening = struct {
|
||||
url: [:0]const u8,
|
||||
message: []const u8,
|
||||
dialog_type: []const u8,
|
||||
};
|
||||
|
||||
pub fn init(allocator: Allocator) !*Notification {
|
||||
const notification = try allocator.create(Notification);
|
||||
errdefer allocator.destroy(notification);
|
||||
|
||||
@@ -903,15 +903,31 @@ pub const JsApi = struct {
|
||||
pub const opener = bridge.property(null, .{ .template = false });
|
||||
|
||||
pub const alert = bridge.function(struct {
|
||||
fn alert(_: *const Window, _: ?[]const u8) void {}
|
||||
}.alert, .{ .noop = true });
|
||||
fn alert(_: *const Window, message: ?[]const u8, page: *Page) void {
|
||||
page._session.notification.dispatch(.javascript_dialog_opening, &.{
|
||||
.url = page.url,
|
||||
.message = message orelse "",
|
||||
.dialog_type = "alert",
|
||||
});
|
||||
}
|
||||
}.alert, .{});
|
||||
pub const confirm = bridge.function(struct {
|
||||
fn confirm(_: *const Window, _: ?[]const u8) bool {
|
||||
fn confirm(_: *const Window, message: ?[]const u8, page: *Page) bool {
|
||||
page._session.notification.dispatch(.javascript_dialog_opening, &.{
|
||||
.url = page.url,
|
||||
.message = message orelse "",
|
||||
.dialog_type = "confirm",
|
||||
});
|
||||
return false;
|
||||
}
|
||||
}.confirm, .{});
|
||||
pub const prompt = bridge.function(struct {
|
||||
fn prompt(_: *const Window, _: ?[]const u8, _: ?[]const u8) ?[]const u8 {
|
||||
fn prompt(_: *const Window, message: ?[]const u8, _: ?[]const u8, page: *Page) ?[]const u8 {
|
||||
page._session.notification.dispatch(.javascript_dialog_opening, &.{
|
||||
.url = page.url,
|
||||
.message = message orelse "",
|
||||
.dialog_type = "prompt",
|
||||
});
|
||||
return null;
|
||||
}
|
||||
}.prompt, .{});
|
||||
|
||||
@@ -431,6 +431,7 @@ pub const BrowserContext = struct {
|
||||
try notification.register(.page_frame_created, self, onPageFrameCreated);
|
||||
try notification.register(.page_dom_content_loaded, self, onPageDOMContentLoaded);
|
||||
try notification.register(.page_loaded, self, onPageLoaded);
|
||||
try notification.register(.javascript_dialog_opening, self, onJavascriptDialogOpening);
|
||||
}
|
||||
|
||||
pub fn deinit(self: *BrowserContext) void {
|
||||
@@ -641,6 +642,11 @@ pub const BrowserContext = struct {
|
||||
return @import("domains/page.zig").pageLoaded(self, msg);
|
||||
}
|
||||
|
||||
pub fn onJavascriptDialogOpening(ctx: *anyopaque, msg: *const Notification.JavascriptDialogOpening) !void {
|
||||
const self: *BrowserContext = @ptrCast(@alignCast(ctx));
|
||||
return @import("domains/page.zig").javascriptDialogOpening(self, msg);
|
||||
}
|
||||
|
||||
pub fn onHttpResponseHeadersDone(ctx: *anyopaque, msg: *const Notification.ResponseHeaderDone) !void {
|
||||
const self: *BrowserContext = @ptrCast(@alignCast(ctx));
|
||||
defer self.resetNotificationArena();
|
||||
|
||||
@@ -48,6 +48,7 @@ pub fn processMessage(cmd: *CDP.Command) !void {
|
||||
close,
|
||||
captureScreenshot,
|
||||
getLayoutMetrics,
|
||||
handleJavaScriptDialog,
|
||||
}, cmd.input.action) orelse return error.UnknownMethod;
|
||||
|
||||
switch (action) {
|
||||
@@ -63,6 +64,7 @@ pub fn processMessage(cmd: *CDP.Command) !void {
|
||||
.close => return close(cmd),
|
||||
.captureScreenshot => return captureScreenshot(cmd),
|
||||
.getLayoutMetrics => return getLayoutMetrics(cmd),
|
||||
.handleJavaScriptDialog => return handleJavaScriptDialog(cmd),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -642,6 +644,32 @@ fn sendPageLifecycle(bc: *CDP.BrowserContext, name: []const u8, timestamp: u64,
|
||||
}, .{ .session_id = session_id });
|
||||
}
|
||||
|
||||
// https://chromedevtools.github.io/devtools-protocol/tot/Page/#method-handleJavaScriptDialog
|
||||
fn handleJavaScriptDialog(cmd: *CDP.Command) !void {
|
||||
// Dialogs auto-dismiss in headless mode. By the time the CDP client
|
||||
// sends this command, the dialog has already returned and there is
|
||||
// no pending dialog to accept or dismiss.
|
||||
_ = try cmd.params(struct {
|
||||
accept: bool,
|
||||
promptText: ?[]const u8 = null,
|
||||
});
|
||||
return cmd.sendError(-32000, "No dialog is showing", .{});
|
||||
}
|
||||
|
||||
// https://chromedevtools.github.io/devtools-protocol/tot/Page/#event-javascriptDialogOpening
|
||||
pub fn javascriptDialogOpening(bc: anytype, event: *const Notification.JavascriptDialogOpening) !void {
|
||||
const session_id = bc.session_id orelse return;
|
||||
var cdp = bc.cdp;
|
||||
|
||||
try cdp.sendEvent("Page.javascriptDialogOpening", .{
|
||||
.url = event.url,
|
||||
.message = event.message,
|
||||
.type = event.dialog_type,
|
||||
.hasBrowserHandler = false,
|
||||
.defaultPrompt = "",
|
||||
}, .{ .session_id = session_id });
|
||||
}
|
||||
|
||||
const LifecycleEvent = struct {
|
||||
frameId: []const u8,
|
||||
loaderId: ?[]const u8,
|
||||
|
||||
Reference in New Issue
Block a user