mirror of
https://github.com/lightpanda-io/browser.git
synced 2025-10-29 07:03:29 +00:00
cdp: implement DOM.performSearch
This commit is contained in:
121
src/cdp/dom.zig
121
src/cdp/dom.zig
@@ -24,6 +24,7 @@ const cdp = @import("cdp.zig");
|
|||||||
const result = cdp.result;
|
const result = cdp.result;
|
||||||
const IncomingMessage = @import("msg.zig").IncomingMessage;
|
const IncomingMessage = @import("msg.zig").IncomingMessage;
|
||||||
const Input = @import("msg.zig").Input;
|
const Input = @import("msg.zig").Input;
|
||||||
|
const css = @import("../dom/css.zig");
|
||||||
|
|
||||||
const parser = @import("netsurf");
|
const parser = @import("netsurf");
|
||||||
|
|
||||||
@@ -32,6 +33,7 @@ const log = std.log.scoped(.cdp);
|
|||||||
const Methods = enum {
|
const Methods = enum {
|
||||||
enable,
|
enable,
|
||||||
getDocument,
|
getDocument,
|
||||||
|
performSearch,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub fn dom(
|
pub fn dom(
|
||||||
@@ -46,6 +48,7 @@ pub fn dom(
|
|||||||
return switch (method) {
|
return switch (method) {
|
||||||
.enable => enable(alloc, msg, ctx),
|
.enable => enable(alloc, msg, ctx),
|
||||||
.getDocument => getDocument(alloc, msg, ctx),
|
.getDocument => getDocument(alloc, msg, ctx),
|
||||||
|
.performSearch => performSearch(alloc, msg, ctx),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -62,6 +65,36 @@ fn enable(
|
|||||||
return result(alloc, input.id, null, null, input.sessionId);
|
return result(alloc, input.id, null, null, input.sessionId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NodeList references tree nodes with an array id.
|
||||||
|
pub const NodeList = struct {
|
||||||
|
coll: List,
|
||||||
|
|
||||||
|
const List = std.ArrayList(*parser.Node);
|
||||||
|
|
||||||
|
pub fn init(alloc: std.mem.Allocator) NodeList {
|
||||||
|
return .{
|
||||||
|
.coll = List.init(alloc),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn deinit(self: *NodeList) void {
|
||||||
|
self.coll.deinit();
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn reset(self: *NodeList) void {
|
||||||
|
self.coll.clearAndFree();
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set(self: *NodeList, node: *parser.Node) !NodeId {
|
||||||
|
for (self.coll.items, 0..) |n, i| {
|
||||||
|
if (n == node) return @intCast(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
try self.coll.append(node);
|
||||||
|
return @intCast(self.coll.items.len);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
const NodeId = u32;
|
const NodeId = u32;
|
||||||
|
|
||||||
const Node = struct {
|
const Node = struct {
|
||||||
@@ -80,13 +113,13 @@ const Node = struct {
|
|||||||
compatibilityMode: []const u8 = "NoQuirksMode",
|
compatibilityMode: []const u8 = "NoQuirksMode",
|
||||||
isScrollable: bool = false,
|
isScrollable: bool = false,
|
||||||
|
|
||||||
fn init(n: *parser.Node) !Node {
|
fn init(n: *parser.Node, id: NodeId) !Node {
|
||||||
const children = try parser.nodeGetChildNodes(n);
|
const children = try parser.nodeGetChildNodes(n);
|
||||||
const ln = try parser.nodeListLength(children);
|
const ln = try parser.nodeListLength(children);
|
||||||
|
|
||||||
return .{
|
return .{
|
||||||
.nodeId = 1,
|
.nodeId = id,
|
||||||
.backendNodeId = 1,
|
.backendNodeId = id,
|
||||||
.nodeType = @intFromEnum(try parser.nodeType(n)),
|
.nodeType = @intFromEnum(try parser.nodeType(n)),
|
||||||
.nodeName = try parser.nodeName(n),
|
.nodeName = try parser.nodeName(n),
|
||||||
.localName = try parser.nodeLocalName(n),
|
.localName = try parser.nodeLocalName(n),
|
||||||
@@ -117,16 +150,90 @@ fn getDocument(
|
|||||||
|
|
||||||
if (page.doc == null) return error.NoDocument;
|
if (page.doc == null) return error.NoDocument;
|
||||||
|
|
||||||
const root = try parser.documentGetDocumentElement(page.doc.?) orelse {
|
const node = parser.documentToNode(page.doc.?);
|
||||||
return error.NoRoot;
|
const id = try ctx.state.nodelist.set(node);
|
||||||
};
|
|
||||||
|
|
||||||
// output
|
// output
|
||||||
const Resp = struct {
|
const Resp = struct {
|
||||||
root: Node,
|
root: Node,
|
||||||
};
|
};
|
||||||
const resp: Resp = .{
|
const resp: Resp = .{
|
||||||
.root = try Node.init(parser.elementToNode(root)),
|
.root = try Node.init(node, id),
|
||||||
|
};
|
||||||
|
|
||||||
|
return result(alloc, input.id, Resp, resp, input.sessionId);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub const NodeSearch = struct {
|
||||||
|
coll: List,
|
||||||
|
name: []u8,
|
||||||
|
alloc: std.mem.Allocator,
|
||||||
|
|
||||||
|
var count: u8 = 0;
|
||||||
|
|
||||||
|
const List = std.ArrayListUnmanaged(NodeId);
|
||||||
|
|
||||||
|
pub fn initCapacity(alloc: std.mem.Allocator, ln: usize) !NodeSearch {
|
||||||
|
count += 1;
|
||||||
|
|
||||||
|
return .{
|
||||||
|
.alloc = alloc,
|
||||||
|
.coll = try List.initCapacity(alloc, ln),
|
||||||
|
.name = try std.fmt.allocPrint(alloc, "{d}", .{count}),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn deinit(self: *NodeSearch) void {
|
||||||
|
self.coll.deinit(self.alloc);
|
||||||
|
self.alloc.free(self.name);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn append(self: *NodeSearch, id: NodeId) !void {
|
||||||
|
try self.coll.append(self.alloc, id);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
pub const NodeSearchList = std.ArrayList(NodeSearch);
|
||||||
|
|
||||||
|
// https://chromedevtools.github.io/devtools-protocol/tot/DOM/#method-performSearch
|
||||||
|
fn performSearch(
|
||||||
|
alloc: std.mem.Allocator,
|
||||||
|
msg: *IncomingMessage,
|
||||||
|
ctx: *Ctx,
|
||||||
|
) ![]const u8 {
|
||||||
|
// input
|
||||||
|
const Params = struct {
|
||||||
|
query: []const u8,
|
||||||
|
includeUserAgentShadowDOM: ?bool = null,
|
||||||
|
};
|
||||||
|
const input = try Input(Params).get(alloc, msg);
|
||||||
|
defer input.deinit();
|
||||||
|
std.debug.assert(input.sessionId != null);
|
||||||
|
log.debug("Req > id {d}, method {s}", .{ input.id, "DOM.performSearch" });
|
||||||
|
|
||||||
|
// retrieve the root node
|
||||||
|
const page = ctx.browser.currentPage() orelse return error.NoPage;
|
||||||
|
|
||||||
|
if (page.doc == null) return error.NoDocument;
|
||||||
|
|
||||||
|
const list = try css.querySelectorAll(alloc, parser.documentToNode(page.doc.?), input.params.query);
|
||||||
|
const ln = list.nodes.items.len;
|
||||||
|
var ns = try NodeSearch.initCapacity(alloc, ln);
|
||||||
|
|
||||||
|
for (list.nodes.items) |n| {
|
||||||
|
const id = try ctx.state.nodelist.set(n);
|
||||||
|
try ns.append(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
try ctx.state.nodesearchlist.append(ns);
|
||||||
|
|
||||||
|
// output
|
||||||
|
const Resp = struct {
|
||||||
|
searchId: []const u8,
|
||||||
|
resultCount: u32,
|
||||||
|
};
|
||||||
|
const resp: Resp = .{
|
||||||
|
.searchId = ns.name,
|
||||||
|
.resultCount = @intCast(ln),
|
||||||
};
|
};
|
||||||
|
|
||||||
return result(alloc, input.id, Resp, resp, input.sessionId);
|
return result(alloc, input.id, Resp, resp, input.sessionId);
|
||||||
|
|||||||
Reference in New Issue
Block a user