mirror of
https://github.com/lightpanda-io/browser.git
synced 2026-03-30 17:18:57 +00:00
Compare commits
20 Commits
build-chec
...
cdp_naviga
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
078e13d8a4 | ||
|
|
cabb029bed | ||
|
|
03ed45637a | ||
|
|
9068fe718e | ||
|
|
5369d25213 | ||
|
|
649d8d1024 | ||
|
|
15d60d845a | ||
|
|
c4b837b598 | ||
|
|
54391238c9 | ||
|
|
d33edc5697 | ||
|
|
16ca8d4b14 | ||
|
|
707ffb4893 | ||
|
|
4782b37216 | ||
|
|
ce197256dd | ||
|
|
e6d644998a | ||
|
|
67bd555e75 | ||
|
|
a10e533701 | ||
|
|
226d9bfc6f | ||
|
|
ea422075c7 | ||
|
|
7f2139f612 |
2
.github/workflows/nightly.yml
vendored
2
.github/workflows/nightly.yml
vendored
@@ -7,7 +7,7 @@ env:
|
|||||||
AWS_REGION: ${{ vars.NIGHTLY_BUILD_AWS_REGION }}
|
AWS_REGION: ${{ vars.NIGHTLY_BUILD_AWS_REGION }}
|
||||||
|
|
||||||
RELEASE: ${{ github.ref_type == 'tag' && github.ref_name || 'nightly' }}
|
RELEASE: ${{ github.ref_type == 'tag' && github.ref_name || 'nightly' }}
|
||||||
VERSION_FLAG: ${{ github.ref_type == 'tag' && format('-Dversion_string={0}', github.ref_name) || format('-Dpre_version={0}', 'nightly') }}
|
VERSION_FLAG: ${{ github.ref_type == 'tag' && format('-Dversion={0}', github.ref_name) || '-Dversion=nightly' }}
|
||||||
|
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
|
|||||||
@@ -170,6 +170,7 @@ You may still encounter errors or crashes. Please open an issue with specifics i
|
|||||||
|
|
||||||
Here are the key features we have implemented:
|
Here are the key features we have implemented:
|
||||||
|
|
||||||
|
- [ ] CORS [#2015](https://github.com/lightpanda-io/browser/issues/2015)
|
||||||
- [x] HTTP loader ([Libcurl](https://curl.se/libcurl/))
|
- [x] HTTP loader ([Libcurl](https://curl.se/libcurl/))
|
||||||
- [x] HTML parser ([html5ever](https://github.com/servo/html5ever))
|
- [x] HTML parser ([html5ever](https://github.com/servo/html5ever))
|
||||||
- [x] DOM tree
|
- [x] DOM tree
|
||||||
|
|||||||
79
build.zig
79
build.zig
@@ -85,15 +85,6 @@ pub fn build(b: *Build) !void {
|
|||||||
break :blk mod;
|
break :blk mod;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Check compilation
|
|
||||||
const check = b.step("check", "Check if lightpanda compiles");
|
|
||||||
|
|
||||||
const check_lib = b.addLibrary(.{
|
|
||||||
.name = "lightpanda_check",
|
|
||||||
.root_module = lightpanda_module,
|
|
||||||
});
|
|
||||||
check.dependOn(&check_lib.step);
|
|
||||||
|
|
||||||
{
|
{
|
||||||
// browser
|
// browser
|
||||||
const exe = b.addExecutable(.{
|
const exe = b.addExecutable(.{
|
||||||
@@ -112,12 +103,6 @@ pub fn build(b: *Build) !void {
|
|||||||
});
|
});
|
||||||
b.installArtifact(exe);
|
b.installArtifact(exe);
|
||||||
|
|
||||||
const exe_check = b.addLibrary(.{
|
|
||||||
.name = "lightpanda_exe_check",
|
|
||||||
.root_module = exe.root_module,
|
|
||||||
});
|
|
||||||
check.dependOn(&exe_check.step);
|
|
||||||
|
|
||||||
const run_cmd = b.addRunArtifact(exe);
|
const run_cmd = b.addRunArtifact(exe);
|
||||||
if (b.args) |args| {
|
if (b.args) |args| {
|
||||||
run_cmd.addArgs(args);
|
run_cmd.addArgs(args);
|
||||||
@@ -147,12 +132,6 @@ pub fn build(b: *Build) !void {
|
|||||||
});
|
});
|
||||||
b.installArtifact(exe);
|
b.installArtifact(exe);
|
||||||
|
|
||||||
const exe_check = b.addLibrary(.{
|
|
||||||
.name = "snapshot_creator_check",
|
|
||||||
.root_module = exe.root_module,
|
|
||||||
});
|
|
||||||
check.dependOn(&exe_check.step);
|
|
||||||
|
|
||||||
const run_cmd = b.addRunArtifact(exe);
|
const run_cmd = b.addRunArtifact(exe);
|
||||||
if (b.args) |args| {
|
if (b.args) |args| {
|
||||||
run_cmd.addArgs(args);
|
run_cmd.addArgs(args);
|
||||||
@@ -191,12 +170,6 @@ pub fn build(b: *Build) !void {
|
|||||||
});
|
});
|
||||||
b.installArtifact(exe);
|
b.installArtifact(exe);
|
||||||
|
|
||||||
const exe_check = b.addLibrary(.{
|
|
||||||
.name = "legacy_test_check",
|
|
||||||
.root_module = exe.root_module,
|
|
||||||
});
|
|
||||||
check.dependOn(&exe_check.step);
|
|
||||||
|
|
||||||
const run_cmd = b.addRunArtifact(exe);
|
const run_cmd = b.addRunArtifact(exe);
|
||||||
if (b.args) |args| {
|
if (b.args) |args| {
|
||||||
run_cmd.addArgs(args);
|
run_cmd.addArgs(args);
|
||||||
@@ -746,39 +719,45 @@ fn buildCurl(
|
|||||||
return lib;
|
return lib;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns `MAJOR.MINOR.PATCH-dev` when `git describe` fails.
|
/// Resolves the semantic version of the build.
|
||||||
|
///
|
||||||
|
/// The base version is read from `build.zig.zon`. This can be overridden
|
||||||
|
/// using the `-Dversion` command-line flag:
|
||||||
|
/// - If the flag contains a full semantic version (e.g., `1.2.3`), it replaces
|
||||||
|
/// the base version entirely.
|
||||||
|
/// - If the flag contains a simple string (e.g., `nightly`), it replaces only
|
||||||
|
/// the pre-release tag of the base version (e.g., `1.0.0-dev` -> `1.0.0-nightly`).
|
||||||
|
///
|
||||||
|
/// For versions that have a pre-release tag and no explicit build metadata,
|
||||||
|
/// this function automatically enriches the version with the git commit count
|
||||||
|
/// and short hash (e.g., `1.0.0-dev.5243+dbe45229`).
|
||||||
fn resolveVersion(b: *std.Build) std.SemanticVersion {
|
fn resolveVersion(b: *std.Build) std.SemanticVersion {
|
||||||
const version_string = b.option([]const u8, "version_string", "Override the version of this build");
|
const opt_version = b.option([]const u8, "version", "Override the version of this build");
|
||||||
if (version_string) |semver_string| {
|
|
||||||
return std.SemanticVersion.parse(semver_string) catch |err| {
|
const version = if (opt_version) |v|
|
||||||
std.debug.panic("Expected -Dversion-string={s} to be a semantic version: {}", .{ semver_string, err });
|
std.SemanticVersion.parse(v) catch blk: {
|
||||||
};
|
var fallback = lightpanda_version;
|
||||||
|
fallback.pre = v;
|
||||||
|
break :blk fallback;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
lightpanda_version;
|
||||||
|
|
||||||
const pre_version = b.option([]const u8, "pre_version", "Override the pre version of this build");
|
// Only enrich versions that have a pre-release field and no explicit build metadata.
|
||||||
const pre = blk: {
|
if (version.pre == null or version.build != null) return version;
|
||||||
if (pre_version) |pre| {
|
|
||||||
break :blk pre;
|
|
||||||
}
|
|
||||||
|
|
||||||
break :blk lightpanda_version.pre;
|
|
||||||
};
|
|
||||||
|
|
||||||
// If it's a stable release (no pre or build metadata in build.zig.zon), use it as is
|
|
||||||
if (pre == null and lightpanda_version.build == null) return lightpanda_version;
|
|
||||||
|
|
||||||
// For dev/nightly versions, calculate the commit count and hash
|
// For dev/nightly versions, calculate the commit count and hash
|
||||||
const git_hash_raw = runGit(b, &.{ "rev-parse", "--short", "HEAD" }) catch return lightpanda_version;
|
const git_hash_raw = runGit(b, &.{ "rev-parse", "--short", "HEAD" }) catch return version;
|
||||||
const commit_hash = std.mem.trim(u8, git_hash_raw, " \n\r");
|
const commit_hash = std.mem.trim(u8, git_hash_raw, " \n\r");
|
||||||
|
|
||||||
const git_count_raw = runGit(b, &.{ "rev-list", "--count", "HEAD" }) catch return lightpanda_version;
|
const git_count_raw = runGit(b, &.{ "rev-list", "--count", "HEAD" }) catch return version;
|
||||||
const commit_count = std.mem.trim(u8, git_count_raw, " \n\r");
|
const commit_count = std.mem.trim(u8, git_count_raw, " \n\r");
|
||||||
|
|
||||||
return .{
|
return .{
|
||||||
.major = lightpanda_version.major,
|
.major = version.major,
|
||||||
.minor = lightpanda_version.minor,
|
.minor = version.minor,
|
||||||
.patch = lightpanda_version.patch,
|
.patch = version.patch,
|
||||||
.pre = b.fmt("{s}.{s}", .{ pre.?, commit_count }),
|
.pre = b.fmt("{s}.{s}", .{ version.pre.?, commit_count }),
|
||||||
.build = commit_hash,
|
.build = commit_hash,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,6 +18,7 @@
|
|||||||
|
|
||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
const builtin = @import("builtin");
|
const builtin = @import("builtin");
|
||||||
|
const log = @import("log.zig");
|
||||||
|
|
||||||
const Allocator = std.mem.Allocator;
|
const Allocator = std.mem.Allocator;
|
||||||
const ArenaAllocator = std.heap.ArenaAllocator;
|
const ArenaAllocator = std.heap.ArenaAllocator;
|
||||||
@@ -62,7 +63,7 @@ pub fn deinit(self: *ArenaPool) void {
|
|||||||
var it = self._leak_track.iterator();
|
var it = self._leak_track.iterator();
|
||||||
while (it.next()) |kv| {
|
while (it.next()) |kv| {
|
||||||
if (kv.value_ptr.* != 0) {
|
if (kv.value_ptr.* != 0) {
|
||||||
std.debug.print("ArenaPool leak detected: '{s}' count={d}\n", .{ kv.key_ptr.*, kv.value_ptr.* });
|
log.err(.bug, "ArenaPool leak", .{ .name = kv.key_ptr.*, .count = kv.value_ptr.* });
|
||||||
has_leaks = true;
|
has_leaks = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -129,11 +130,11 @@ pub fn release(self: *ArenaPool, allocator: Allocator) void {
|
|||||||
if (self._leak_track.getPtr(entry.debug)) |count| {
|
if (self._leak_track.getPtr(entry.debug)) |count| {
|
||||||
count.* -= 1;
|
count.* -= 1;
|
||||||
if (count.* < 0) {
|
if (count.* < 0) {
|
||||||
std.debug.print("ArenaPool double-free detected: '{s}'\n", .{entry.debug});
|
log.err(.bug, "ArenaPool double-free", .{ .name = entry.debug });
|
||||||
@panic("ArenaPool: double-free detected");
|
@panic("ArenaPool: double-free detected");
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
std.debug.print("ArenaPool release of untracked arena: '{s}'\n", .{entry.debug});
|
log.err(.bug, "ArenaPool release unknown", .{ .name = entry.debug });
|
||||||
@panic("ArenaPool: release of untracked arena");
|
@panic("ArenaPool: release of untracked arena");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -74,6 +74,8 @@ const EventListeners = struct {
|
|||||||
page_network_idle: List = .{},
|
page_network_idle: List = .{},
|
||||||
page_network_almost_idle: List = .{},
|
page_network_almost_idle: List = .{},
|
||||||
page_frame_created: List = .{},
|
page_frame_created: List = .{},
|
||||||
|
page_dom_content_loaded: List = .{},
|
||||||
|
page_loaded: List = .{},
|
||||||
http_request_fail: List = .{},
|
http_request_fail: List = .{},
|
||||||
http_request_start: List = .{},
|
http_request_start: List = .{},
|
||||||
http_request_intercept: List = .{},
|
http_request_intercept: List = .{},
|
||||||
@@ -91,6 +93,8 @@ const Events = union(enum) {
|
|||||||
page_network_idle: *const PageNetworkIdle,
|
page_network_idle: *const PageNetworkIdle,
|
||||||
page_network_almost_idle: *const PageNetworkAlmostIdle,
|
page_network_almost_idle: *const PageNetworkAlmostIdle,
|
||||||
page_frame_created: *const PageFrameCreated,
|
page_frame_created: *const PageFrameCreated,
|
||||||
|
page_dom_content_loaded: *const PageDOMContentLoaded,
|
||||||
|
page_loaded: *const PageLoaded,
|
||||||
http_request_fail: *const RequestFail,
|
http_request_fail: *const RequestFail,
|
||||||
http_request_start: *const RequestStart,
|
http_request_start: *const RequestStart,
|
||||||
http_request_intercept: *const RequestIntercept,
|
http_request_intercept: *const RequestIntercept,
|
||||||
@@ -137,6 +141,18 @@ pub const PageFrameCreated = struct {
|
|||||||
timestamp: u64,
|
timestamp: u64,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
pub const PageDOMContentLoaded = struct {
|
||||||
|
req_id: u32,
|
||||||
|
frame_id: u32,
|
||||||
|
timestamp: u64,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub const PageLoaded = struct {
|
||||||
|
req_id: u32,
|
||||||
|
frame_id: u32,
|
||||||
|
timestamp: u64,
|
||||||
|
};
|
||||||
|
|
||||||
pub const RequestStart = struct {
|
pub const RequestStart = struct {
|
||||||
transfer: *Transfer,
|
transfer: *Transfer,
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -22,7 +22,6 @@ const net = std.net;
|
|||||||
const posix = std.posix;
|
const posix = std.posix;
|
||||||
|
|
||||||
const Allocator = std.mem.Allocator;
|
const Allocator = std.mem.Allocator;
|
||||||
const ArenaAllocator = std.heap.ArenaAllocator;
|
|
||||||
|
|
||||||
const log = @import("log.zig");
|
const log = @import("log.zig");
|
||||||
const App = @import("App.zig");
|
const App = @import("App.zig");
|
||||||
|
|||||||
@@ -19,17 +19,13 @@
|
|||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
|
|
||||||
const Allocator = std.mem.Allocator;
|
const Allocator = std.mem.Allocator;
|
||||||
const ArenaAllocator = std.heap.ArenaAllocator;
|
|
||||||
|
|
||||||
const js = @import("js/js.zig");
|
const js = @import("js/js.zig");
|
||||||
const log = @import("../log.zig");
|
|
||||||
const App = @import("../App.zig");
|
const App = @import("../App.zig");
|
||||||
const HttpClient = @import("HttpClient.zig");
|
const HttpClient = @import("HttpClient.zig");
|
||||||
|
|
||||||
const ArenaPool = App.ArenaPool;
|
const ArenaPool = App.ArenaPool;
|
||||||
|
|
||||||
const IS_DEBUG = @import("builtin").mode == .Debug;
|
|
||||||
|
|
||||||
const Session = @import("Session.zig");
|
const Session = @import("Session.zig");
|
||||||
const Notification = @import("../Notification.zig");
|
const Notification = @import("../Notification.zig");
|
||||||
|
|
||||||
|
|||||||
@@ -425,7 +425,7 @@ fn dispatchNode(self: *EventManager, target: *Node, event: *Event, comptime opts
|
|||||||
ls.deinit();
|
ls.deinit();
|
||||||
}
|
}
|
||||||
|
|
||||||
const activation_state = ActivationState.create(event, target, page);
|
const activation_state = try ActivationState.create(event, target, page);
|
||||||
|
|
||||||
// Defer runs even on early return - ensures event phase is reset
|
// Defer runs even on early return - ensures event phase is reset
|
||||||
// and default actions execute (unless prevented)
|
// and default actions execute (unless prevented)
|
||||||
@@ -820,7 +820,7 @@ const ActivationState = struct {
|
|||||||
|
|
||||||
const Input = Element.Html.Input;
|
const Input = Element.Html.Input;
|
||||||
|
|
||||||
fn create(event: *const Event, target: *Node, page: *Page) ?ActivationState {
|
fn create(event: *const Event, target: *Node, page: *Page) !?ActivationState {
|
||||||
if (event._type_string.eql(comptime .wrap("click")) == false) {
|
if (event._type_string.eql(comptime .wrap("click")) == false) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -27,7 +27,6 @@ const IS_DEBUG = builtin.mode == .Debug;
|
|||||||
|
|
||||||
const log = @import("../log.zig");
|
const log = @import("../log.zig");
|
||||||
|
|
||||||
const App = @import("../App.zig");
|
|
||||||
const String = @import("../string.zig").String;
|
const String = @import("../string.zig").String;
|
||||||
|
|
||||||
const Mime = @import("Mime.zig");
|
const Mime = @import("Mime.zig");
|
||||||
@@ -43,7 +42,6 @@ const URL = @import("URL.zig");
|
|||||||
const Blob = @import("webapi/Blob.zig");
|
const Blob = @import("webapi/Blob.zig");
|
||||||
const Node = @import("webapi/Node.zig");
|
const Node = @import("webapi/Node.zig");
|
||||||
const Event = @import("webapi/Event.zig");
|
const Event = @import("webapi/Event.zig");
|
||||||
const EventTarget = @import("webapi/EventTarget.zig");
|
|
||||||
const CData = @import("webapi/CData.zig");
|
const CData = @import("webapi/CData.zig");
|
||||||
const Element = @import("webapi/Element.zig");
|
const Element = @import("webapi/Element.zig");
|
||||||
const HtmlElement = @import("webapi/element/Html.zig");
|
const HtmlElement = @import("webapi/element/Html.zig");
|
||||||
@@ -59,7 +57,6 @@ const AbstractRange = @import("webapi/AbstractRange.zig");
|
|||||||
const MutationObserver = @import("webapi/MutationObserver.zig");
|
const MutationObserver = @import("webapi/MutationObserver.zig");
|
||||||
const IntersectionObserver = @import("webapi/IntersectionObserver.zig");
|
const IntersectionObserver = @import("webapi/IntersectionObserver.zig");
|
||||||
const CustomElementDefinition = @import("webapi/CustomElementDefinition.zig");
|
const CustomElementDefinition = @import("webapi/CustomElementDefinition.zig");
|
||||||
const storage = @import("webapi/storage/storage.zig");
|
|
||||||
const PageTransitionEvent = @import("webapi/event/PageTransitionEvent.zig");
|
const PageTransitionEvent = @import("webapi/event/PageTransitionEvent.zig");
|
||||||
const SubmitEvent = @import("webapi/event/SubmitEvent.zig");
|
const SubmitEvent = @import("webapi/event/SubmitEvent.zig");
|
||||||
const NavigationKind = @import("webapi/navigation/root.zig").NavigationKind;
|
const NavigationKind = @import("webapi/navigation/root.zig").NavigationKind;
|
||||||
@@ -67,7 +64,6 @@ const KeyboardEvent = @import("webapi/event/KeyboardEvent.zig");
|
|||||||
const MouseEvent = @import("webapi/event/MouseEvent.zig");
|
const MouseEvent = @import("webapi/event/MouseEvent.zig");
|
||||||
|
|
||||||
const HttpClient = @import("HttpClient.zig");
|
const HttpClient = @import("HttpClient.zig");
|
||||||
const ArenaPool = App.ArenaPool;
|
|
||||||
|
|
||||||
const timestamp = @import("../datetime.zig").timestamp;
|
const timestamp = @import("../datetime.zig").timestamp;
|
||||||
const milliTimestamp = @import("../datetime.zig").milliTimestamp;
|
const milliTimestamp = @import("../datetime.zig").milliTimestamp;
|
||||||
@@ -385,12 +381,9 @@ pub fn getTitle(self: *Page) !?[]const u8 {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add comon headers for a request:
|
// Add common headers for a request:
|
||||||
// * cookies
|
|
||||||
// * referer
|
// * referer
|
||||||
pub fn headersForRequest(self: *Page, temp: Allocator, url: [:0]const u8, headers: *HttpClient.Headers) !void {
|
pub fn headersForRequest(self: *Page, headers: *HttpClient.Headers) !void {
|
||||||
try self.requestCookie(.{}).headersForRequest(temp, url, headers);
|
|
||||||
|
|
||||||
// Build the referer
|
// Build the referer
|
||||||
const referer = blk: {
|
const referer = blk: {
|
||||||
if (self.referer_header == null) {
|
if (self.referer_header == null) {
|
||||||
@@ -494,7 +487,6 @@ pub fn navigate(self: *Page, request_url: [:0]const u8, opts: NavigateOpts) !voi
|
|||||||
return error.InjectBlankFailed;
|
return error.InjectBlankFailed;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
self.documentIsComplete();
|
|
||||||
|
|
||||||
session.notification.dispatch(.page_navigate, &.{
|
session.notification.dispatch(.page_navigate, &.{
|
||||||
.frame_id = self._frame_id,
|
.frame_id = self._frame_id,
|
||||||
@@ -526,6 +518,8 @@ pub fn navigate(self: *Page, request_url: [:0]const u8, opts: NavigateOpts) !voi
|
|||||||
|
|
||||||
// force next request id manually b/c we won't create a real req.
|
// force next request id manually b/c we won't create a real req.
|
||||||
_ = session.browser.http_client.incrReqId();
|
_ = session.browser.http_client.incrReqId();
|
||||||
|
|
||||||
|
self.documentIsComplete();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -545,8 +539,6 @@ pub fn navigate(self: *Page, request_url: [:0]const u8, opts: NavigateOpts) !voi
|
|||||||
if (opts.header) |hdr| {
|
if (opts.header) |hdr| {
|
||||||
try headers.add(hdr);
|
try headers.add(hdr);
|
||||||
}
|
}
|
||||||
try self.requestCookie(.{ .is_navigation = true }).headersForRequest(self.arena, self.url, &headers);
|
|
||||||
|
|
||||||
// We dispatch page_navigate event before sending the request.
|
// We dispatch page_navigate event before sending the request.
|
||||||
// It ensures the event page_navigated is not dispatched before this one.
|
// It ensures the event page_navigated is not dispatched before this one.
|
||||||
session.notification.dispatch(.page_navigate, &.{
|
session.notification.dispatch(.page_navigate, &.{
|
||||||
@@ -573,6 +565,7 @@ pub fn navigate(self: *Page, request_url: [:0]const u8, opts: NavigateOpts) !voi
|
|||||||
.headers = headers,
|
.headers = headers,
|
||||||
.body = opts.body,
|
.body = opts.body,
|
||||||
.cookie_jar = &session.cookie_jar,
|
.cookie_jar = &session.cookie_jar,
|
||||||
|
.cookie_origin = self.url,
|
||||||
.resource_type = .document,
|
.resource_type = .document,
|
||||||
.notification = self._session.notification,
|
.notification = self._session.notification,
|
||||||
.header_callback = pageHeaderDoneCallback,
|
.header_callback = pageHeaderDoneCallback,
|
||||||
@@ -746,6 +739,12 @@ pub fn _documentIsLoaded(self: *Page) !void {
|
|||||||
self.document.asEventTarget(),
|
self.document.asEventTarget(),
|
||||||
event,
|
event,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
self._session.notification.dispatch(.page_dom_content_loaded, &.{
|
||||||
|
.frame_id = self._frame_id,
|
||||||
|
.req_id = self._req_id,
|
||||||
|
.timestamp = timestamp(.monotonic),
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn scriptsCompletedLoading(self: *Page) void {
|
pub fn scriptsCompletedLoading(self: *Page) void {
|
||||||
@@ -804,19 +803,6 @@ pub fn documentIsComplete(self: *Page) void {
|
|||||||
self._documentIsComplete() catch |err| {
|
self._documentIsComplete() catch |err| {
|
||||||
log.err(.page, "document is complete", .{ .err = err, .type = self._type, .url = self.url });
|
log.err(.page, "document is complete", .{ .err = err, .type = self._type, .url = self.url });
|
||||||
};
|
};
|
||||||
|
|
||||||
if (self._navigated_options) |no| {
|
|
||||||
// _navigated_options will be null in special short-circuit cases, like
|
|
||||||
// "navigating" to about:blank, in which case this notification has
|
|
||||||
// already been sent
|
|
||||||
self._session.notification.dispatch(.page_navigated, &.{
|
|
||||||
.frame_id = self._frame_id,
|
|
||||||
.req_id = self._req_id,
|
|
||||||
.opts = no,
|
|
||||||
.url = self.url,
|
|
||||||
.timestamp = timestamp(.monotonic),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn _documentIsComplete(self: *Page) !void {
|
fn _documentIsComplete(self: *Page) !void {
|
||||||
@@ -835,6 +821,12 @@ fn _documentIsComplete(self: *Page) !void {
|
|||||||
try self._event_manager.dispatchDirect(window_target, event, self.window._on_load, .{ .inject_target = false, .context = "page load" });
|
try self._event_manager.dispatchDirect(window_target, event, self.window._on_load, .{ .inject_target = false, .context = "page load" });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
self._session.notification.dispatch(.page_loaded, &.{
|
||||||
|
.frame_id = self._frame_id,
|
||||||
|
.req_id = self._req_id,
|
||||||
|
.timestamp = timestamp(.monotonic),
|
||||||
|
});
|
||||||
|
|
||||||
if (self._event_manager.hasDirectListeners(window_target, "pageshow", self.window._on_pageshow)) {
|
if (self._event_manager.hasDirectListeners(window_target, "pageshow", self.window._on_pageshow)) {
|
||||||
const pageshow_event = (try PageTransitionEvent.initTrusted(comptime .wrap("pageshow"), .{}, self)).asEvent();
|
const pageshow_event = (try PageTransitionEvent.initTrusted(comptime .wrap("pageshow"), .{}, self)).asEvent();
|
||||||
try self._event_manager.dispatchDirect(window_target, pageshow_event, self.window._on_pageshow, .{ .context = "page show" });
|
try self._event_manager.dispatchDirect(window_target, pageshow_event, self.window._on_pageshow, .{ .context = "page show" });
|
||||||
@@ -887,6 +879,19 @@ fn pageHeaderDoneCallback(transfer: *HttpClient.Transfer) !bool {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (self._navigated_options) |no| {
|
||||||
|
// _navigated_options will be null in special short-circuit cases, like
|
||||||
|
// "navigating" to about:blank, in which case this notification has
|
||||||
|
// already been sent
|
||||||
|
self._session.notification.dispatch(.page_navigated, &.{
|
||||||
|
.frame_id = self._frame_id,
|
||||||
|
.req_id = self._req_id,
|
||||||
|
.opts = no,
|
||||||
|
.url = self.url,
|
||||||
|
.timestamp = timestamp(.monotonic),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1036,6 +1041,7 @@ fn pageDoneCallback(ctx: *anyopaque) !void {
|
|||||||
});
|
});
|
||||||
|
|
||||||
parser.parse(html);
|
parser.parse(html);
|
||||||
|
self._parse_state = .complete;
|
||||||
self.documentIsComplete();
|
self.documentIsComplete();
|
||||||
},
|
},
|
||||||
else => unreachable,
|
else => unreachable,
|
||||||
@@ -3554,19 +3560,6 @@ pub fn insertText(self: *Page, v: []const u8) !void {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const RequestCookieOpts = struct {
|
|
||||||
is_http: bool = true,
|
|
||||||
is_navigation: bool = false,
|
|
||||||
};
|
|
||||||
pub fn requestCookie(self: *const Page, opts: RequestCookieOpts) HttpClient.RequestCookie {
|
|
||||||
return .{
|
|
||||||
.jar = &self._session.cookie_jar,
|
|
||||||
.origin = self.url,
|
|
||||||
.is_http = opts.is_http,
|
|
||||||
.is_navigation = opts.is_navigation,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
fn asUint(comptime string: anytype) std.meta.Int(
|
fn asUint(comptime string: anytype) std.meta.Int(
|
||||||
.unsigned,
|
.unsigned,
|
||||||
@bitSizeOf(@TypeOf(string.*)) - 8, // (- 8) to exclude sentinel 0
|
@bitSizeOf(@TypeOf(string.*)) - 8, // (- 8) to exclude sentinel 0
|
||||||
|
|||||||
@@ -21,12 +21,9 @@ const lp = @import("lightpanda");
|
|||||||
const builtin = @import("builtin");
|
const builtin = @import("builtin");
|
||||||
|
|
||||||
const log = @import("../log.zig");
|
const log = @import("../log.zig");
|
||||||
const App = @import("../App.zig");
|
|
||||||
|
|
||||||
const Page = @import("Page.zig");
|
const Page = @import("Page.zig");
|
||||||
const Session = @import("Session.zig");
|
const Session = @import("Session.zig");
|
||||||
const Browser = @import("Browser.zig");
|
|
||||||
const Factory = @import("Factory.zig");
|
|
||||||
const HttpClient = @import("HttpClient.zig");
|
const HttpClient = @import("HttpClient.zig");
|
||||||
|
|
||||||
const IS_DEBUG = builtin.mode == .Debug;
|
const IS_DEBUG = builtin.mode == .Debug;
|
||||||
|
|||||||
@@ -28,12 +28,10 @@ const String = @import("../string.zig").String;
|
|||||||
const js = @import("js/js.zig");
|
const js = @import("js/js.zig");
|
||||||
const URL = @import("URL.zig");
|
const URL = @import("URL.zig");
|
||||||
const Page = @import("Page.zig");
|
const Page = @import("Page.zig");
|
||||||
const Browser = @import("Browser.zig");
|
|
||||||
|
|
||||||
const Element = @import("webapi/Element.zig");
|
const Element = @import("webapi/Element.zig");
|
||||||
|
|
||||||
const Allocator = std.mem.Allocator;
|
const Allocator = std.mem.Allocator;
|
||||||
const ArrayList = std.ArrayList;
|
|
||||||
|
|
||||||
const IS_DEBUG = builtin.mode == .Debug;
|
const IS_DEBUG = builtin.mode == .Debug;
|
||||||
|
|
||||||
@@ -138,9 +136,9 @@ fn clearList(list: *std.DoublyLinkedList) void {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn getHeaders(self: *ScriptManager, arena: Allocator, url: [:0]const u8) !net_http.Headers {
|
fn getHeaders(self: *ScriptManager) !net_http.Headers {
|
||||||
var headers = try self.client.newHeaders();
|
var headers = try self.client.newHeaders();
|
||||||
try self.page.headersForRequest(arena, url, &headers);
|
try self.page.headersForRequest(&headers);
|
||||||
return headers;
|
return headers;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -280,9 +278,10 @@ pub fn addFromElement(self: *ScriptManager, comptime from_parser: bool, script_e
|
|||||||
.ctx = script,
|
.ctx = script,
|
||||||
.method = .GET,
|
.method = .GET,
|
||||||
.frame_id = page._frame_id,
|
.frame_id = page._frame_id,
|
||||||
.headers = try self.getHeaders(arena, url),
|
.headers = try self.getHeaders(),
|
||||||
.blocking = is_blocking,
|
.blocking = is_blocking,
|
||||||
.cookie_jar = &page._session.cookie_jar,
|
.cookie_jar = &page._session.cookie_jar,
|
||||||
|
.cookie_origin = page.url,
|
||||||
.resource_type = .script,
|
.resource_type = .script,
|
||||||
.notification = page._session.notification,
|
.notification = page._session.notification,
|
||||||
.start_callback = if (log.enabled(.http, .debug)) Script.startCallback else null,
|
.start_callback = if (log.enabled(.http, .debug)) Script.startCallback else null,
|
||||||
@@ -405,8 +404,9 @@ pub fn preloadImport(self: *ScriptManager, url: [:0]const u8, referrer: []const
|
|||||||
.ctx = script,
|
.ctx = script,
|
||||||
.method = .GET,
|
.method = .GET,
|
||||||
.frame_id = page._frame_id,
|
.frame_id = page._frame_id,
|
||||||
.headers = try self.getHeaders(arena, url),
|
.headers = try self.getHeaders(),
|
||||||
.cookie_jar = &page._session.cookie_jar,
|
.cookie_jar = &page._session.cookie_jar,
|
||||||
|
.cookie_origin = page.url,
|
||||||
.resource_type = .script,
|
.resource_type = .script,
|
||||||
.notification = page._session.notification,
|
.notification = page._session.notification,
|
||||||
.start_callback = if (log.enabled(.http, .debug)) Script.startCallback else null,
|
.start_callback = if (log.enabled(.http, .debug)) Script.startCallback else null,
|
||||||
@@ -508,10 +508,11 @@ pub fn getAsyncImport(self: *ScriptManager, url: [:0]const u8, cb: ImportAsync.C
|
|||||||
.url = url,
|
.url = url,
|
||||||
.method = .GET,
|
.method = .GET,
|
||||||
.frame_id = page._frame_id,
|
.frame_id = page._frame_id,
|
||||||
.headers = try self.getHeaders(arena, url),
|
.headers = try self.getHeaders(),
|
||||||
.ctx = script,
|
.ctx = script,
|
||||||
.resource_type = .script,
|
.resource_type = .script,
|
||||||
.cookie_jar = &page._session.cookie_jar,
|
.cookie_jar = &page._session.cookie_jar,
|
||||||
|
.cookie_origin = page.url,
|
||||||
.notification = page._session.notification,
|
.notification = page._session.notification,
|
||||||
.start_callback = if (log.enabled(.http, .debug)) Script.startCallback else null,
|
.start_callback = if (log.enabled(.http, .debug)) Script.startCallback else null,
|
||||||
.header_callback = Script.headerCallback,
|
.header_callback = Script.headerCallback,
|
||||||
@@ -654,7 +655,6 @@ pub const Script = struct {
|
|||||||
debug_transfer_aborted: bool = false,
|
debug_transfer_aborted: bool = false,
|
||||||
debug_transfer_bytes_received: usize = 0,
|
debug_transfer_bytes_received: usize = 0,
|
||||||
debug_transfer_notified_fail: bool = false,
|
debug_transfer_notified_fail: bool = false,
|
||||||
debug_transfer_redirecting: bool = false,
|
|
||||||
debug_transfer_intercept_state: u8 = 0,
|
debug_transfer_intercept_state: u8 = 0,
|
||||||
debug_transfer_auth_challenge: bool = false,
|
debug_transfer_auth_challenge: bool = false,
|
||||||
debug_transfer_easy_id: usize = 0,
|
debug_transfer_easy_id: usize = 0,
|
||||||
@@ -730,7 +730,6 @@ pub const Script = struct {
|
|||||||
.a3 = self.debug_transfer_aborted,
|
.a3 = self.debug_transfer_aborted,
|
||||||
.a4 = self.debug_transfer_bytes_received,
|
.a4 = self.debug_transfer_bytes_received,
|
||||||
.a5 = self.debug_transfer_notified_fail,
|
.a5 = self.debug_transfer_notified_fail,
|
||||||
.a6 = self.debug_transfer_redirecting,
|
|
||||||
.a7 = self.debug_transfer_intercept_state,
|
.a7 = self.debug_transfer_intercept_state,
|
||||||
.a8 = self.debug_transfer_auth_challenge,
|
.a8 = self.debug_transfer_auth_challenge,
|
||||||
.a9 = self.debug_transfer_easy_id,
|
.a9 = self.debug_transfer_easy_id,
|
||||||
@@ -739,10 +738,9 @@ pub const Script = struct {
|
|||||||
.b3 = transfer.aborted,
|
.b3 = transfer.aborted,
|
||||||
.b4 = transfer.bytes_received,
|
.b4 = transfer.bytes_received,
|
||||||
.b5 = transfer._notified_fail,
|
.b5 = transfer._notified_fail,
|
||||||
.b6 = transfer._redirecting,
|
|
||||||
.b7 = @intFromEnum(transfer._intercept_state),
|
.b7 = @intFromEnum(transfer._intercept_state),
|
||||||
.b8 = transfer._auth_challenge != null,
|
.b8 = transfer._auth_challenge != null,
|
||||||
.b9 = if (transfer._conn) |c| @intFromPtr(c.easy) else 0,
|
.b9 = if (transfer._conn) |c| @intFromPtr(c._easy) else 0,
|
||||||
});
|
});
|
||||||
self.header_callback_called = true;
|
self.header_callback_called = true;
|
||||||
self.debug_transfer_id = transfer.id;
|
self.debug_transfer_id = transfer.id;
|
||||||
@@ -750,10 +748,9 @@ pub const Script = struct {
|
|||||||
self.debug_transfer_aborted = transfer.aborted;
|
self.debug_transfer_aborted = transfer.aborted;
|
||||||
self.debug_transfer_bytes_received = transfer.bytes_received;
|
self.debug_transfer_bytes_received = transfer.bytes_received;
|
||||||
self.debug_transfer_notified_fail = transfer._notified_fail;
|
self.debug_transfer_notified_fail = transfer._notified_fail;
|
||||||
self.debug_transfer_redirecting = transfer._redirecting;
|
|
||||||
self.debug_transfer_intercept_state = @intFromEnum(transfer._intercept_state);
|
self.debug_transfer_intercept_state = @intFromEnum(transfer._intercept_state);
|
||||||
self.debug_transfer_auth_challenge = transfer._auth_challenge != null;
|
self.debug_transfer_auth_challenge = transfer._auth_challenge != null;
|
||||||
self.debug_transfer_easy_id = if (transfer._conn) |c| @intFromPtr(c.easy) else 0;
|
self.debug_transfer_easy_id = if (transfer._conn) |c| @intFromPtr(c._easy) else 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
lp.assert(self.source.remote.capacity == 0, "ScriptManager.Header buffer", .{ .capacity = self.source.remote.capacity });
|
lp.assert(self.source.remote.capacity == 0, "ScriptManager.Header buffer", .{ .capacity = self.source.remote.capacity });
|
||||||
|
|||||||
@@ -128,7 +128,7 @@ fn _constructor(self: *Caller, func: anytype, info: FunctionCallbackInfo) !void
|
|||||||
const new_this_handle = info.getThis();
|
const new_this_handle = info.getThis();
|
||||||
var this = js.Object{ .local = local, .handle = new_this_handle };
|
var this = js.Object{ .local = local, .handle = new_this_handle };
|
||||||
if (@typeInfo(ReturnType) == .error_union) {
|
if (@typeInfo(ReturnType) == .error_union) {
|
||||||
const non_error_res = res catch |err| return err;
|
const non_error_res = try res;
|
||||||
this = try local.mapZigInstanceToJs(new_this_handle, non_error_res);
|
this = try local.mapZigInstanceToJs(new_this_handle, non_error_res);
|
||||||
} else {
|
} else {
|
||||||
this = try local.mapZigInstanceToJs(new_this_handle, res);
|
this = try local.mapZigInstanceToJs(new_this_handle, res);
|
||||||
|
|||||||
@@ -22,7 +22,6 @@ const log = @import("../../log.zig");
|
|||||||
|
|
||||||
const js = @import("js.zig");
|
const js = @import("js.zig");
|
||||||
const Env = @import("Env.zig");
|
const Env = @import("Env.zig");
|
||||||
const bridge = @import("bridge.zig");
|
|
||||||
const Origin = @import("Origin.zig");
|
const Origin = @import("Origin.zig");
|
||||||
const Scheduler = @import("Scheduler.zig");
|
const Scheduler = @import("Scheduler.zig");
|
||||||
|
|
||||||
|
|||||||
@@ -26,7 +26,6 @@ const App = @import("../../App.zig");
|
|||||||
const log = @import("../../log.zig");
|
const log = @import("../../log.zig");
|
||||||
|
|
||||||
const bridge = @import("bridge.zig");
|
const bridge = @import("bridge.zig");
|
||||||
const Origin = @import("Origin.zig");
|
|
||||||
const Context = @import("Context.zig");
|
const Context = @import("Context.zig");
|
||||||
const Isolate = @import("Isolate.zig");
|
const Isolate = @import("Isolate.zig");
|
||||||
const Platform = @import("Platform.zig");
|
const Platform = @import("Platform.zig");
|
||||||
@@ -34,7 +33,6 @@ const Snapshot = @import("Snapshot.zig");
|
|||||||
const Inspector = @import("Inspector.zig");
|
const Inspector = @import("Inspector.zig");
|
||||||
|
|
||||||
const Page = @import("../Page.zig");
|
const Page = @import("../Page.zig");
|
||||||
const Session = @import("../Session.zig");
|
|
||||||
const Window = @import("../webapi/Window.zig");
|
const Window = @import("../webapi/Window.zig");
|
||||||
|
|
||||||
const JsApis = bridge.JsApis;
|
const JsApis = bridge.JsApis;
|
||||||
|
|||||||
@@ -21,7 +21,6 @@ const js = @import("js.zig");
|
|||||||
const v8 = js.v8;
|
const v8 = js.v8;
|
||||||
|
|
||||||
const log = @import("../../log.zig");
|
const log = @import("../../log.zig");
|
||||||
const Session = @import("../Session.zig");
|
|
||||||
|
|
||||||
const Function = @This();
|
const Function = @This();
|
||||||
|
|
||||||
|
|||||||
@@ -32,7 +32,6 @@ const js = @import("js.zig");
|
|||||||
const Session = @import("../Session.zig");
|
const Session = @import("../Session.zig");
|
||||||
|
|
||||||
const v8 = js.v8;
|
const v8 = js.v8;
|
||||||
const Allocator = std.mem.Allocator;
|
|
||||||
|
|
||||||
const Identity = @This();
|
const Identity = @This();
|
||||||
|
|
||||||
|
|||||||
@@ -17,7 +17,6 @@
|
|||||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
const Page = @import("../Page.zig");
|
|
||||||
const Session = @import("../Session.zig");
|
const Session = @import("../Session.zig");
|
||||||
const log = @import("../../log.zig");
|
const log = @import("../../log.zig");
|
||||||
const string = @import("../../string.zig");
|
const string = @import("../../string.zig");
|
||||||
@@ -33,7 +32,6 @@ const IS_DEBUG = @import("builtin").mode == .Debug;
|
|||||||
|
|
||||||
const v8 = js.v8;
|
const v8 = js.v8;
|
||||||
const CallOpts = Caller.CallOpts;
|
const CallOpts = Caller.CallOpts;
|
||||||
const Allocator = std.mem.Allocator;
|
|
||||||
|
|
||||||
// Where js.Context has a lifetime tied to the page, and holds the
|
// Where js.Context has a lifetime tied to the page, and holds the
|
||||||
// v8::Global<v8::Context>, this has a much shorter lifetime and holds a
|
// v8::Global<v8::Context>, this has a much shorter lifetime and holds a
|
||||||
|
|||||||
@@ -20,8 +20,6 @@ const std = @import("std");
|
|||||||
const js = @import("js.zig");
|
const js = @import("js.zig");
|
||||||
const v8 = js.v8;
|
const v8 = js.v8;
|
||||||
|
|
||||||
const Session = @import("../Session.zig");
|
|
||||||
|
|
||||||
const Promise = @This();
|
const Promise = @This();
|
||||||
|
|
||||||
local: *const js.Local,
|
local: *const js.Local,
|
||||||
|
|||||||
@@ -25,7 +25,6 @@ const IS_DEBUG = @import("builtin").mode == .Debug;
|
|||||||
|
|
||||||
const v8 = js.v8;
|
const v8 = js.v8;
|
||||||
const JsApis = bridge.JsApis;
|
const JsApis = bridge.JsApis;
|
||||||
const Allocator = std.mem.Allocator;
|
|
||||||
|
|
||||||
const Snapshot = @This();
|
const Snapshot = @This();
|
||||||
|
|
||||||
|
|||||||
@@ -25,7 +25,6 @@ const v8 = js.v8;
|
|||||||
const IS_DEBUG = @import("builtin").mode == .Debug;
|
const IS_DEBUG = @import("builtin").mode == .Debug;
|
||||||
|
|
||||||
const Allocator = std.mem.Allocator;
|
const Allocator = std.mem.Allocator;
|
||||||
const Session = @import("../Session.zig");
|
|
||||||
|
|
||||||
const Value = @This();
|
const Value = @This();
|
||||||
|
|
||||||
|
|||||||
@@ -18,15 +18,12 @@
|
|||||||
|
|
||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
const js = @import("js.zig");
|
const js = @import("js.zig");
|
||||||
const lp = @import("lightpanda");
|
|
||||||
const log = @import("../../log.zig");
|
|
||||||
const Page = @import("../Page.zig");
|
const Page = @import("../Page.zig");
|
||||||
const Session = @import("../Session.zig");
|
const Session = @import("../Session.zig");
|
||||||
|
|
||||||
const v8 = js.v8;
|
const v8 = js.v8;
|
||||||
|
|
||||||
const Caller = @import("Caller.zig");
|
const Caller = @import("Caller.zig");
|
||||||
const Context = @import("Context.zig");
|
|
||||||
|
|
||||||
const IS_DEBUG = @import("builtin").mode == .Debug;
|
const IS_DEBUG = @import("builtin").mode == .Debug;
|
||||||
|
|
||||||
|
|||||||
@@ -21,7 +21,6 @@ const std = @import("std");
|
|||||||
const Page = @import("Page.zig");
|
const Page = @import("Page.zig");
|
||||||
const URL = @import("URL.zig");
|
const URL = @import("URL.zig");
|
||||||
const TreeWalker = @import("webapi/TreeWalker.zig");
|
const TreeWalker = @import("webapi/TreeWalker.zig");
|
||||||
const CData = @import("webapi/CData.zig");
|
|
||||||
const Element = @import("webapi/Element.zig");
|
const Element = @import("webapi/Element.zig");
|
||||||
const Node = @import("webapi/Node.zig");
|
const Node = @import("webapi/Node.zig");
|
||||||
const isAllWhitespace = @import("../string.zig").isAllWhitespace;
|
const isAllWhitespace = @import("../string.zig").isAllWhitespace;
|
||||||
|
|||||||
@@ -24,7 +24,6 @@ const Page = @import("../Page.zig");
|
|||||||
|
|
||||||
const Node = @import("Node.zig");
|
const Node = @import("Node.zig");
|
||||||
const Element = @import("Element.zig");
|
const Element = @import("Element.zig");
|
||||||
const DOMException = @import("DOMException.zig");
|
|
||||||
const Custom = @import("element/html/Custom.zig");
|
const Custom = @import("element/html/Custom.zig");
|
||||||
const CustomElementDefinition = @import("CustomElementDefinition.zig");
|
const CustomElementDefinition = @import("CustomElementDefinition.zig");
|
||||||
|
|
||||||
|
|||||||
@@ -18,7 +18,6 @@
|
|||||||
|
|
||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
const js = @import("../js/js.zig");
|
const js = @import("../js/js.zig");
|
||||||
const String = @import("../../string.zig").String;
|
|
||||||
|
|
||||||
const Page = @import("../Page.zig");
|
const Page = @import("../Page.zig");
|
||||||
const Node = @import("Node.zig");
|
const Node = @import("Node.zig");
|
||||||
|
|||||||
@@ -19,10 +19,8 @@
|
|||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
|
|
||||||
const String = @import("../../string.zig").String;
|
const String = @import("../../string.zig").String;
|
||||||
const log = @import("../../log.zig");
|
|
||||||
|
|
||||||
const js = @import("../js/js.zig");
|
const js = @import("../js/js.zig");
|
||||||
const color = @import("../color.zig");
|
|
||||||
const Page = @import("../Page.zig");
|
const Page = @import("../Page.zig");
|
||||||
|
|
||||||
/// https://developer.mozilla.org/en-US/docs/Web/API/ImageData/ImageData
|
/// https://developer.mozilla.org/en-US/docs/Web/API/ImageData/ImageData
|
||||||
|
|||||||
@@ -28,8 +28,6 @@ const DocumentFragment = @import("DocumentFragment.zig");
|
|||||||
const AbstractRange = @import("AbstractRange.zig");
|
const AbstractRange = @import("AbstractRange.zig");
|
||||||
const DOMRect = @import("DOMRect.zig");
|
const DOMRect = @import("DOMRect.zig");
|
||||||
|
|
||||||
const Allocator = std.mem.Allocator;
|
|
||||||
|
|
||||||
const Range = @This();
|
const Range = @This();
|
||||||
|
|
||||||
_proto: *AbstractRange,
|
_proto: *AbstractRange,
|
||||||
|
|||||||
@@ -17,7 +17,6 @@
|
|||||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
const log = @import("../../log.zig");
|
|
||||||
|
|
||||||
const js = @import("../js/js.zig");
|
const js = @import("../js/js.zig");
|
||||||
const Page = @import("../Page.zig");
|
const Page = @import("../Page.zig");
|
||||||
@@ -27,7 +26,6 @@ const Range = @import("Range.zig");
|
|||||||
const AbstractRange = @import("AbstractRange.zig");
|
const AbstractRange = @import("AbstractRange.zig");
|
||||||
const Node = @import("Node.zig");
|
const Node = @import("Node.zig");
|
||||||
const Event = @import("Event.zig");
|
const Event = @import("Event.zig");
|
||||||
const Document = @import("Document.zig");
|
|
||||||
|
|
||||||
/// https://w3c.github.io/selection-api/
|
/// https://w3c.github.io/selection-api/
|
||||||
const Selection = @This();
|
const Selection = @This();
|
||||||
|
|||||||
@@ -19,7 +19,6 @@
|
|||||||
const js = @import("../js/js.zig");
|
const js = @import("../js/js.zig");
|
||||||
const Page = @import("../Page.zig");
|
const Page = @import("../Page.zig");
|
||||||
const EventTarget = @import("EventTarget.zig");
|
const EventTarget = @import("EventTarget.zig");
|
||||||
const Window = @import("Window.zig");
|
|
||||||
|
|
||||||
const VisualViewport = @This();
|
const VisualViewport = @This();
|
||||||
|
|
||||||
|
|||||||
@@ -16,7 +16,6 @@
|
|||||||
// You should have received a copy of the GNU Affero General Public License
|
// You should have received a copy of the GNU Affero General Public License
|
||||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
const String = @import("../../../string.zig").String;
|
|
||||||
const js = @import("../../js/js.zig");
|
const js = @import("../../js/js.zig");
|
||||||
const Page = @import("../../Page.zig");
|
const Page = @import("../../Page.zig");
|
||||||
const CData = @import("../CData.zig");
|
const CData = @import("../CData.zig");
|
||||||
|
|||||||
@@ -20,7 +20,6 @@
|
|||||||
|
|
||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
const lp = @import("lightpanda");
|
const lp = @import("lightpanda");
|
||||||
const log = @import("../../../log.zig");
|
|
||||||
const crypto = @import("../../../sys/libcrypto.zig");
|
const crypto = @import("../../../sys/libcrypto.zig");
|
||||||
|
|
||||||
const Page = @import("../../Page.zig");
|
const Page = @import("../../Page.zig");
|
||||||
|
|||||||
@@ -20,12 +20,10 @@
|
|||||||
|
|
||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
const lp = @import("lightpanda");
|
const lp = @import("lightpanda");
|
||||||
const log = @import("../../../log.zig");
|
|
||||||
const crypto = @import("../../../sys/libcrypto.zig");
|
const crypto = @import("../../../sys/libcrypto.zig");
|
||||||
|
|
||||||
const Page = @import("../../Page.zig");
|
const Page = @import("../../Page.zig");
|
||||||
const js = @import("../../js/js.zig");
|
const js = @import("../../js/js.zig");
|
||||||
const Algorithm = @import("algorithm.zig").Algorithm;
|
|
||||||
|
|
||||||
const CryptoKey = @import("../CryptoKey.zig");
|
const CryptoKey = @import("../CryptoKey.zig");
|
||||||
|
|
||||||
|
|||||||
@@ -22,7 +22,6 @@ const reflect = @import("../../reflect.zig");
|
|||||||
const log = @import("../../../log.zig");
|
const log = @import("../../../log.zig");
|
||||||
|
|
||||||
const global_event_handlers = @import("../global_event_handlers.zig");
|
const global_event_handlers = @import("../global_event_handlers.zig");
|
||||||
const GlobalEventHandlersLookup = global_event_handlers.Lookup;
|
|
||||||
const GlobalEventHandler = global_event_handlers.Handler;
|
const GlobalEventHandler = global_event_handlers.Handler;
|
||||||
|
|
||||||
const Page = @import("../../Page.zig");
|
const Page = @import("../../Page.zig");
|
||||||
|
|||||||
@@ -16,7 +16,6 @@
|
|||||||
// You should have received a copy of the GNU Affero General Public License
|
// You should have received a copy of the GNU Affero General Public License
|
||||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
const log = @import("../../../../log.zig");
|
|
||||||
const js = @import("../../../js/js.zig");
|
const js = @import("../../../js/js.zig");
|
||||||
const Page = @import("../../../Page.zig");
|
const Page = @import("../../../Page.zig");
|
||||||
const Window = @import("../../Window.zig");
|
const Window = @import("../../Window.zig");
|
||||||
|
|||||||
@@ -5,10 +5,6 @@ const URL = @import("../../../URL.zig");
|
|||||||
const Node = @import("../../Node.zig");
|
const Node = @import("../../Node.zig");
|
||||||
const Element = @import("../../Element.zig");
|
const Element = @import("../../Element.zig");
|
||||||
const HtmlElement = @import("../Html.zig");
|
const HtmlElement = @import("../Html.zig");
|
||||||
const Event = @import("../../Event.zig");
|
|
||||||
const log = @import("../../../../log.zig");
|
|
||||||
|
|
||||||
const IS_DEBUG = @import("builtin").mode == .Debug;
|
|
||||||
|
|
||||||
const Image = @This();
|
const Image = @This();
|
||||||
_proto: *HtmlElement,
|
_proto: *HtmlElement,
|
||||||
|
|||||||
@@ -17,7 +17,6 @@
|
|||||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
|
|
||||||
const log = @import("../../../../log.zig");
|
|
||||||
const js = @import("../../../js/js.zig");
|
const js = @import("../../../js/js.zig");
|
||||||
const Page = @import("../../../Page.zig");
|
const Page = @import("../../../Page.zig");
|
||||||
|
|
||||||
|
|||||||
@@ -22,7 +22,6 @@ const js = @import("../../js/js.zig");
|
|||||||
const Page = @import("../../Page.zig");
|
const Page = @import("../../Page.zig");
|
||||||
const Session = @import("../../Session.zig");
|
const Session = @import("../../Session.zig");
|
||||||
const Event = @import("../Event.zig");
|
const Event = @import("../Event.zig");
|
||||||
const Allocator = std.mem.Allocator;
|
|
||||||
|
|
||||||
const CompositionEvent = @This();
|
const CompositionEvent = @This();
|
||||||
|
|
||||||
|
|||||||
@@ -24,7 +24,6 @@ const Session = @import("../../Session.zig");
|
|||||||
const js = @import("../../js/js.zig");
|
const js = @import("../../js/js.zig");
|
||||||
|
|
||||||
const Event = @import("../Event.zig");
|
const Event = @import("../Event.zig");
|
||||||
const UIEvent = @import("UIEvent.zig");
|
|
||||||
|
|
||||||
const FormData = @import("../net/FormData.zig");
|
const FormData = @import("../net/FormData.zig");
|
||||||
|
|
||||||
|
|||||||
@@ -22,7 +22,6 @@ const js = @import("../../js/js.zig");
|
|||||||
const Page = @import("../../Page.zig");
|
const Page = @import("../../Page.zig");
|
||||||
const Session = @import("../../Session.zig");
|
const Session = @import("../../Session.zig");
|
||||||
const Event = @import("../Event.zig");
|
const Event = @import("../Event.zig");
|
||||||
const Allocator = std.mem.Allocator;
|
|
||||||
|
|
||||||
const PromiseRejectionEvent = @This();
|
const PromiseRejectionEvent = @This();
|
||||||
|
|
||||||
|
|||||||
@@ -27,8 +27,6 @@ const Page = @import("../../Page.zig");
|
|||||||
const Event = @import("../Event.zig");
|
const Event = @import("../Event.zig");
|
||||||
const EventTarget = @import("../EventTarget.zig");
|
const EventTarget = @import("../EventTarget.zig");
|
||||||
|
|
||||||
const IS_DEBUG = @import("builtin").mode == .Debug;
|
|
||||||
|
|
||||||
// https://developer.mozilla.org/en-US/docs/Web/API/Navigation
|
// https://developer.mozilla.org/en-US/docs/Web/API/Navigation
|
||||||
const Navigation = @This();
|
const Navigation = @This();
|
||||||
|
|
||||||
|
|||||||
@@ -18,7 +18,6 @@
|
|||||||
|
|
||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
const URL = @import("../URL.zig");
|
const URL = @import("../URL.zig");
|
||||||
const EventTarget = @import("../EventTarget.zig");
|
|
||||||
const NavigationState = @import("root.zig").NavigationState;
|
const NavigationState = @import("root.zig").NavigationState;
|
||||||
const Page = @import("../../Page.zig");
|
const Page = @import("../../Page.zig");
|
||||||
const js = @import("../../js/js.zig");
|
const js = @import("../../js/js.zig");
|
||||||
|
|||||||
@@ -80,7 +80,7 @@ pub fn init(input: Input, options: ?InitOpts, page: *Page) !js.Promise {
|
|||||||
if (request._headers) |h| {
|
if (request._headers) |h| {
|
||||||
try h.populateHttpHeader(page.call_arena, &headers);
|
try h.populateHttpHeader(page.call_arena, &headers);
|
||||||
}
|
}
|
||||||
try page.headersForRequest(page.arena, request._url, &headers);
|
try page.headersForRequest(&headers);
|
||||||
|
|
||||||
if (comptime IS_DEBUG) {
|
if (comptime IS_DEBUG) {
|
||||||
log.debug(.http, "fetch", .{ .url = request._url });
|
log.debug(.http, "fetch", .{ .url = request._url });
|
||||||
@@ -95,6 +95,7 @@ pub fn init(input: Input, options: ?InitOpts, page: *Page) !js.Promise {
|
|||||||
.headers = headers,
|
.headers = headers,
|
||||||
.resource_type = .fetch,
|
.resource_type = .fetch,
|
||||||
.cookie_jar = &page._session.cookie_jar,
|
.cookie_jar = &page._session.cookie_jar,
|
||||||
|
.cookie_origin = page.url,
|
||||||
.notification = page._session.notification,
|
.notification = page._session.notification,
|
||||||
.start_callback = httpStartCallback,
|
.start_callback = httpStartCallback,
|
||||||
.header_callback = httpHeaderDoneCallback,
|
.header_callback = httpHeaderDoneCallback,
|
||||||
|
|||||||
@@ -22,7 +22,6 @@ const log = @import("../../../log.zig");
|
|||||||
|
|
||||||
const js = @import("../../js/js.zig");
|
const js = @import("../../js/js.zig");
|
||||||
const Page = @import("../../Page.zig");
|
const Page = @import("../../Page.zig");
|
||||||
const Node = @import("../Node.zig");
|
|
||||||
const Form = @import("../element/html/Form.zig");
|
const Form = @import("../element/html/Form.zig");
|
||||||
const Element = @import("../Element.zig");
|
const Element = @import("../Element.zig");
|
||||||
const KeyValueList = @import("../KeyValueList.zig");
|
const KeyValueList = @import("../KeyValueList.zig");
|
||||||
|
|||||||
@@ -29,7 +29,6 @@ const Page = @import("../../Page.zig");
|
|||||||
const Session = @import("../../Session.zig");
|
const Session = @import("../../Session.zig");
|
||||||
|
|
||||||
const Node = @import("../Node.zig");
|
const Node = @import("../Node.zig");
|
||||||
const Blob = @import("../Blob.zig");
|
|
||||||
const Event = @import("../Event.zig");
|
const Event = @import("../Event.zig");
|
||||||
const Headers = @import("Headers.zig");
|
const Headers = @import("Headers.zig");
|
||||||
const EventTarget = @import("../EventTarget.zig");
|
const EventTarget = @import("../EventTarget.zig");
|
||||||
@@ -225,7 +224,7 @@ pub fn send(self: *XMLHttpRequest, body_: ?[]const u8) !void {
|
|||||||
|
|
||||||
try self._request_headers.populateHttpHeader(page.call_arena, &headers);
|
try self._request_headers.populateHttpHeader(page.call_arena, &headers);
|
||||||
if (cookie_support) {
|
if (cookie_support) {
|
||||||
try page.headersForRequest(self._arena, self._url, &headers);
|
try page.headersForRequest(&headers);
|
||||||
}
|
}
|
||||||
|
|
||||||
try http_client.request(.{
|
try http_client.request(.{
|
||||||
@@ -236,6 +235,7 @@ pub fn send(self: *XMLHttpRequest, body_: ?[]const u8) !void {
|
|||||||
.frame_id = page._frame_id,
|
.frame_id = page._frame_id,
|
||||||
.body = self._request_body,
|
.body = self._request_body,
|
||||||
.cookie_jar = if (cookie_support) &page._session.cookie_jar else null,
|
.cookie_jar = if (cookie_support) &page._session.cookie_jar else null,
|
||||||
|
.cookie_origin = page.url,
|
||||||
.resource_type = .xhr,
|
.resource_type = .xhr,
|
||||||
.notification = page._session.notification,
|
.notification = page._session.notification,
|
||||||
.start_callback = httpStartCallback,
|
.start_callback = httpStartCallback,
|
||||||
|
|||||||
@@ -25,7 +25,6 @@ const json = std.json;
|
|||||||
const Incrementing = @import("id.zig").Incrementing;
|
const Incrementing = @import("id.zig").Incrementing;
|
||||||
|
|
||||||
const log = @import("../log.zig");
|
const log = @import("../log.zig");
|
||||||
const App = @import("../App.zig");
|
|
||||||
const Notification = @import("../Notification.zig");
|
const Notification = @import("../Notification.zig");
|
||||||
|
|
||||||
const Client = @import("../Server.zig").Client;
|
const Client = @import("../Server.zig").Client;
|
||||||
@@ -35,7 +34,6 @@ const Browser = @import("../browser/Browser.zig");
|
|||||||
const Session = @import("../browser/Session.zig");
|
const Session = @import("../browser/Session.zig");
|
||||||
const Page = @import("../browser/Page.zig");
|
const Page = @import("../browser/Page.zig");
|
||||||
const Mime = @import("../browser/Mime.zig");
|
const Mime = @import("../browser/Mime.zig");
|
||||||
const HttpClient = @import("../browser/HttpClient.zig");
|
|
||||||
|
|
||||||
const InterceptState = @import("domains/fetch.zig").InterceptState;
|
const InterceptState = @import("domains/fetch.zig").InterceptState;
|
||||||
|
|
||||||
@@ -429,6 +427,8 @@ pub fn BrowserContext(comptime CDP_T: type) type {
|
|||||||
try notification.register(.page_navigate, self, onPageNavigate);
|
try notification.register(.page_navigate, self, onPageNavigate);
|
||||||
try notification.register(.page_navigated, self, onPageNavigated);
|
try notification.register(.page_navigated, self, onPageNavigated);
|
||||||
try notification.register(.page_frame_created, self, onPageFrameCreated);
|
try notification.register(.page_frame_created, self, onPageFrameCreated);
|
||||||
|
try notification.register(.page_dom_content_loaded, self, onPageDOMContentLoaded);
|
||||||
|
try notification.register(.page_loaded, self, onPageLoaded);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn deinit(self: *Self) void {
|
pub fn deinit(self: *Self) void {
|
||||||
@@ -470,8 +470,8 @@ pub fn BrowserContext(comptime CDP_T: type) type {
|
|||||||
if (self.http_proxy_changed) {
|
if (self.http_proxy_changed) {
|
||||||
// has to be called after browser.closeSession, since it won't
|
// has to be called after browser.closeSession, since it won't
|
||||||
// work if there are active connections.
|
// work if there are active connections.
|
||||||
browser.http_client.restoreOriginalProxy() catch |err| {
|
browser.http_client.changeProxy(null) catch |err| {
|
||||||
log.warn(.http, "restoreOriginalProxy", .{ .err = err });
|
log.warn(.http, "changeProxy", .{ .err = err });
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
self.intercept_state.deinit();
|
self.intercept_state.deinit();
|
||||||
@@ -604,6 +604,16 @@ pub fn BrowserContext(comptime CDP_T: type) type {
|
|||||||
return @import("domains/page.zig").pageFrameCreated(self, msg);
|
return @import("domains/page.zig").pageFrameCreated(self, msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn onPageDOMContentLoaded(ctx: *anyopaque, msg: *const Notification.PageDOMContentLoaded) !void {
|
||||||
|
const self: *Self = @ptrCast(@alignCast(ctx));
|
||||||
|
return @import("domains/page.zig").pageDOMContentLoaded(self, msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn onPageLoaded(ctx: *anyopaque, msg: *const Notification.PageLoaded) !void {
|
||||||
|
const self: *Self = @ptrCast(@alignCast(ctx));
|
||||||
|
return @import("domains/page.zig").pageLoaded(self, msg);
|
||||||
|
}
|
||||||
|
|
||||||
pub fn onPageNetworkIdle(ctx: *anyopaque, msg: *const Notification.PageNetworkIdle) !void {
|
pub fn onPageNetworkIdle(ctx: *anyopaque, msg: *const Notification.PageNetworkIdle) !void {
|
||||||
const self: *Self = @ptrCast(@alignCast(ctx));
|
const self: *Self = @ptrCast(@alignCast(ctx));
|
||||||
return @import("domains/page.zig").pageNetworkIdle(self, msg);
|
return @import("domains/page.zig").pageNetworkIdle(self, msg);
|
||||||
|
|||||||
@@ -18,7 +18,6 @@
|
|||||||
|
|
||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
const lp = @import("lightpanda");
|
const lp = @import("lightpanda");
|
||||||
const log = @import("../../log.zig");
|
|
||||||
const markdown = lp.markdown;
|
const markdown = lp.markdown;
|
||||||
const SemanticTree = lp.SemanticTree;
|
const SemanticTree = lp.SemanticTree;
|
||||||
const interactive = lp.interactive;
|
const interactive = lp.interactive;
|
||||||
|
|||||||
@@ -351,6 +351,10 @@ pub const TransferAsRequestWriter = struct {
|
|||||||
try jws.objectField(hdr.name);
|
try jws.objectField(hdr.name);
|
||||||
try jws.write(hdr.value);
|
try jws.write(hdr.value);
|
||||||
}
|
}
|
||||||
|
if (try transfer.getCookieString()) |cookies| {
|
||||||
|
try jws.objectField("Cookie");
|
||||||
|
try jws.write(cookies[0 .. cookies.len - 1]);
|
||||||
|
}
|
||||||
try jws.endObject();
|
try jws.endObject();
|
||||||
}
|
}
|
||||||
try jws.endObject();
|
try jws.endObject();
|
||||||
|
|||||||
@@ -385,7 +385,6 @@ pub fn pageNavigated(arena: Allocator, bc: anytype, event: *const Notification.P
|
|||||||
// things, but no session.
|
// things, but no session.
|
||||||
const session_id = bc.session_id orelse return;
|
const session_id = bc.session_id orelse return;
|
||||||
|
|
||||||
const timestamp = event.timestamp;
|
|
||||||
const frame_id = &id.toFrameId(event.frame_id);
|
const frame_id = &id.toFrameId(event.frame_id);
|
||||||
const loader_id = &id.toLoaderId(event.req_id);
|
const loader_id = &id.toLoaderId(event.req_id);
|
||||||
|
|
||||||
@@ -437,9 +436,9 @@ pub fn pageNavigated(arena: Allocator, bc: anytype, event: *const Notification.P
|
|||||||
const page = bc.session.currentPage() orelse return error.PageNotLoaded;
|
const page = bc.session.currentPage() orelse return error.PageNotLoaded;
|
||||||
|
|
||||||
// When we actually recreated the context we should have the inspector send
|
// When we actually recreated the context we should have the inspector send
|
||||||
// this event, see: resetContextGroup Sending this event will tell the
|
// this event, see: resetContextGroup. Sending this event will tell the
|
||||||
// client that the context ids they had are invalid and the context shouls
|
// client that the context ids they had are invalid and the context should
|
||||||
// be dropped The client will expect us to send new contextCreated events,
|
// be dropped. The client will expect us to send new contextCreated events,
|
||||||
// such that the client has new id's for the active contexts.
|
// such that the client has new id's for the active contexts.
|
||||||
// Only send executionContextsCleared for main frame navigations. For child
|
// Only send executionContextsCleared for main frame navigations. For child
|
||||||
// frames (iframes), clearing all contexts would destroy the main frame's
|
// frames (iframes), clearing all contexts would destroy the main frame's
|
||||||
@@ -449,6 +448,18 @@ pub fn pageNavigated(arena: Allocator, bc: anytype, event: *const Notification.P
|
|||||||
try cdp.sendEvent("Runtime.executionContextsCleared", null, .{ .session_id = session_id });
|
try cdp.sendEvent("Runtime.executionContextsCleared", null, .{ .session_id = session_id });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// frameNavigated event
|
||||||
|
try cdp.sendEvent("Page.frameNavigated", .{
|
||||||
|
.type = "Navigation",
|
||||||
|
.frame = Frame{
|
||||||
|
.id = frame_id,
|
||||||
|
.url = event.url,
|
||||||
|
.loaderId = loader_id,
|
||||||
|
.securityOrigin = bc.security_origin,
|
||||||
|
.secureContextType = bc.secure_context_type,
|
||||||
|
},
|
||||||
|
}, .{ .session_id = session_id });
|
||||||
|
|
||||||
{
|
{
|
||||||
const aux_data = try std.fmt.allocPrint(arena, "{{\"isDefault\":true,\"type\":\"default\",\"frameId\":\"{s}\",\"loaderId\":\"{s}\"}}", .{ frame_id, loader_id });
|
const aux_data = try std.fmt.allocPrint(arena, "{{\"isDefault\":true,\"type\":\"default\",\"frameId\":\"{s}\",\"loaderId\":\"{s}\"}}", .{ frame_id, loader_id });
|
||||||
|
|
||||||
@@ -498,18 +509,22 @@ pub fn pageNavigated(arena: Allocator, bc: anytype, event: *const Notification.P
|
|||||||
// chromedp client expects to receive the events is this order.
|
// chromedp client expects to receive the events is this order.
|
||||||
// see https://github.com/chromedp/chromedp/issues/1558
|
// see https://github.com/chromedp/chromedp/issues/1558
|
||||||
try cdp.sendEvent("DOM.documentUpdated", null, .{ .session_id = session_id });
|
try cdp.sendEvent("DOM.documentUpdated", null, .{ .session_id = session_id });
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn pageDOMContentLoaded(bc: anytype, event: *const Notification.PageDOMContentLoaded) !void {
|
||||||
|
const session_id = bc.session_id orelse return;
|
||||||
|
const timestamp = event.timestamp;
|
||||||
|
var cdp = bc.cdp;
|
||||||
|
|
||||||
// domContentEventFired event
|
|
||||||
// TODO: partially hard coded
|
|
||||||
try cdp.sendEvent(
|
try cdp.sendEvent(
|
||||||
"Page.domContentEventFired",
|
"Page.domContentEventFired",
|
||||||
.{ .timestamp = timestamp },
|
.{ .timestamp = timestamp },
|
||||||
.{ .session_id = session_id },
|
.{ .session_id = session_id },
|
||||||
);
|
);
|
||||||
|
|
||||||
// lifecycle DOMContentLoaded event
|
|
||||||
// TODO: partially hard coded
|
|
||||||
if (bc.page_life_cycle_events) {
|
if (bc.page_life_cycle_events) {
|
||||||
|
const frame_id = &id.toFrameId(event.frame_id);
|
||||||
|
const loader_id = &id.toLoaderId(event.req_id);
|
||||||
try cdp.sendEvent("Page.lifecycleEvent", LifecycleEvent{
|
try cdp.sendEvent("Page.lifecycleEvent", LifecycleEvent{
|
||||||
.timestamp = timestamp,
|
.timestamp = timestamp,
|
||||||
.name = "DOMContentLoaded",
|
.name = "DOMContentLoaded",
|
||||||
@@ -517,16 +532,23 @@ pub fn pageNavigated(arena: Allocator, bc: anytype, event: *const Notification.P
|
|||||||
.loaderId = loader_id,
|
.loaderId = loader_id,
|
||||||
}, .{ .session_id = session_id });
|
}, .{ .session_id = session_id });
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn pageLoaded(bc: anytype, event: *const Notification.PageLoaded) !void {
|
||||||
|
const session_id = bc.session_id orelse return;
|
||||||
|
const timestamp = event.timestamp;
|
||||||
|
var cdp = bc.cdp;
|
||||||
|
|
||||||
|
const frame_id = &id.toFrameId(event.frame_id);
|
||||||
|
|
||||||
// loadEventFired event
|
|
||||||
try cdp.sendEvent(
|
try cdp.sendEvent(
|
||||||
"Page.loadEventFired",
|
"Page.loadEventFired",
|
||||||
.{ .timestamp = timestamp },
|
.{ .timestamp = timestamp },
|
||||||
.{ .session_id = session_id },
|
.{ .session_id = session_id },
|
||||||
);
|
);
|
||||||
|
|
||||||
// lifecycle DOMContentLoaded event
|
|
||||||
if (bc.page_life_cycle_events) {
|
if (bc.page_life_cycle_events) {
|
||||||
|
const loader_id = &id.toLoaderId(event.req_id);
|
||||||
try cdp.sendEvent("Page.lifecycleEvent", LifecycleEvent{
|
try cdp.sendEvent("Page.lifecycleEvent", LifecycleEvent{
|
||||||
.timestamp = timestamp,
|
.timestamp = timestamp,
|
||||||
.name = "load",
|
.name = "load",
|
||||||
@@ -535,7 +557,6 @@ pub fn pageNavigated(arena: Allocator, bc: anytype, event: *const Notification.P
|
|||||||
}, .{ .session_id = session_id });
|
}, .{ .session_id = session_id });
|
||||||
}
|
}
|
||||||
|
|
||||||
// frameStoppedLoading
|
|
||||||
return cdp.sendEvent("Page.frameStoppedLoading", .{
|
return cdp.sendEvent("Page.frameStoppedLoading", .{
|
||||||
.frameId = frame_id,
|
.frameId = frame_id,
|
||||||
}, .{ .session_id = session_id });
|
}, .{ .session_id = session_id });
|
||||||
|
|||||||
@@ -24,9 +24,6 @@ const log = @import("../../log.zig");
|
|||||||
const URL = @import("../../browser/URL.zig");
|
const URL = @import("../../browser/URL.zig");
|
||||||
const js = @import("../../browser/js/js.zig");
|
const js = @import("../../browser/js/js.zig");
|
||||||
|
|
||||||
// TODO: hard coded IDs
|
|
||||||
const LOADER_ID = "LOADERID42AA389647D702B4D805F49A";
|
|
||||||
|
|
||||||
pub fn processMessage(cmd: anytype) !void {
|
pub fn processMessage(cmd: anytype) !void {
|
||||||
const action = std.meta.stringToEnum(enum {
|
const action = std.meta.stringToEnum(enum {
|
||||||
getTargets,
|
getTargets,
|
||||||
|
|||||||
@@ -17,7 +17,6 @@
|
|||||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
const IS_DEBUG = @import("builtin").mode == .Debug;
|
|
||||||
|
|
||||||
pub fn toPageId(comptime id_type: enum { frame_id, loader_id }, input: []const u8) !u32 {
|
pub fn toPageId(comptime id_type: enum { frame_id, loader_id }, input: []const u8) !u32 {
|
||||||
const err = switch (comptime id_type) {
|
const err = switch (comptime id_type) {
|
||||||
|
|||||||
@@ -19,10 +19,6 @@
|
|||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
const json = std.json;
|
const json = std.json;
|
||||||
const posix = std.posix;
|
const posix = std.posix;
|
||||||
const Allocator = std.mem.Allocator;
|
|
||||||
const ArenaAllocator = std.heap.ArenaAllocator;
|
|
||||||
|
|
||||||
const Testing = @This();
|
|
||||||
|
|
||||||
const CDP = @import("CDP.zig");
|
const CDP = @import("CDP.zig");
|
||||||
const Server = @import("../Server.zig");
|
const Server = @import("../Server.zig");
|
||||||
|
|||||||
@@ -49,9 +49,6 @@ const Opts = struct {
|
|||||||
|
|
||||||
pub var opts = Opts{};
|
pub var opts = Opts{};
|
||||||
|
|
||||||
// synchronizes writes to the output
|
|
||||||
var out_lock: Thread.Mutex = .{};
|
|
||||||
|
|
||||||
// synchronizes access to last_log
|
// synchronizes access to last_log
|
||||||
var last_log_lock: Thread.Mutex = .{};
|
var last_log_lock: Thread.Mutex = .{};
|
||||||
|
|
||||||
|
|||||||
@@ -110,5 +110,3 @@ pub fn handleRead(server: *Server, arena: std.mem.Allocator, req: protocol.Reque
|
|||||||
return server.sendError(req_id, .InternalError, "Failed to serialize resource content");
|
return server.sendError(req_id, .InternalError, "Failed to serialize resource content");
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
const testing = @import("../testing.zig");
|
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
const lp = @import("lightpanda");
|
|
||||||
const protocol = @import("protocol.zig");
|
const protocol = @import("protocol.zig");
|
||||||
const resources = @import("resources.zig");
|
const resources = @import("resources.zig");
|
||||||
const Server = @import("Server.zig");
|
const Server = @import("Server.zig");
|
||||||
|
|||||||
@@ -4,9 +4,7 @@ const lp = @import("lightpanda");
|
|||||||
const log = lp.log;
|
const log = lp.log;
|
||||||
const js = lp.js;
|
const js = lp.js;
|
||||||
|
|
||||||
const Element = @import("../browser/webapi/Element.zig");
|
|
||||||
const DOMNode = @import("../browser/webapi/Node.zig");
|
const DOMNode = @import("../browser/webapi/Node.zig");
|
||||||
const Selector = @import("../browser/webapi/selector/Selector.zig");
|
|
||||||
const protocol = @import("protocol.zig");
|
const protocol = @import("protocol.zig");
|
||||||
const Server = @import("Server.zig");
|
const Server = @import("Server.zig");
|
||||||
const CDPNode = @import("../cdp/Node.zig");
|
const CDPNode = @import("../cdp/Node.zig");
|
||||||
|
|||||||
@@ -461,7 +461,7 @@ fn drainQueue(self: *Runtime) void {
|
|||||||
self.releaseConnection(conn);
|
self.releaseConnection(conn);
|
||||||
continue;
|
continue;
|
||||||
};
|
};
|
||||||
libcurl.curl_multi_add_handle(multi, conn.easy) catch |err| {
|
libcurl.curl_multi_add_handle(multi, conn._easy) catch |err| {
|
||||||
lp.log.err(.app, "curl multi add", .{ .err = err });
|
lp.log.err(.app, "curl multi add", .{ .err = err });
|
||||||
self.releaseConnection(conn);
|
self.releaseConnection(conn);
|
||||||
};
|
};
|
||||||
@@ -565,7 +565,7 @@ pub fn getConnection(self: *Runtime) ?*net_http.Connection {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn releaseConnection(self: *Runtime, conn: *net_http.Connection) void {
|
pub fn releaseConnection(self: *Runtime, conn: *net_http.Connection) void {
|
||||||
conn.reset() catch |err| {
|
conn.reset(self.config, self.ca_blob) catch |err| {
|
||||||
lp.assert(false, "couldn't reset curl easy", .{ .err = err });
|
lp.assert(false, "couldn't reset curl easy", .{ .err = err });
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -17,10 +17,6 @@
|
|||||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
const builtin = @import("builtin");
|
|
||||||
const posix = std.posix;
|
|
||||||
const Allocator = std.mem.Allocator;
|
|
||||||
const ArenaAllocator = std.heap.ArenaAllocator;
|
|
||||||
|
|
||||||
const Config = @import("../Config.zig");
|
const Config = @import("../Config.zig");
|
||||||
const libcurl = @import("../sys/libcurl.zig");
|
const libcurl = @import("../sys/libcurl.zig");
|
||||||
@@ -29,18 +25,12 @@ const log = @import("lightpanda").log;
|
|||||||
const assert = @import("lightpanda").assert;
|
const assert = @import("lightpanda").assert;
|
||||||
|
|
||||||
pub const ENABLE_DEBUG = false;
|
pub const ENABLE_DEBUG = false;
|
||||||
const IS_DEBUG = builtin.mode == .Debug;
|
|
||||||
|
|
||||||
pub const Blob = libcurl.CurlBlob;
|
pub const Blob = libcurl.CurlBlob;
|
||||||
pub const WaitFd = libcurl.CurlWaitFd;
|
pub const WaitFd = libcurl.CurlWaitFd;
|
||||||
pub const writefunc_error = libcurl.curl_writefunc_error;
|
pub const writefunc_error = libcurl.curl_writefunc_error;
|
||||||
|
|
||||||
const Error = libcurl.Error;
|
const Error = libcurl.Error;
|
||||||
const ErrorMulti = libcurl.ErrorMulti;
|
|
||||||
const errorFromCode = libcurl.errorFromCode;
|
|
||||||
const errorMFromCode = libcurl.errorMFromCode;
|
|
||||||
const errorCheck = libcurl.errorCheck;
|
|
||||||
const errorMCheck = libcurl.errorMCheck;
|
|
||||||
|
|
||||||
pub fn curl_version() [*c]const u8 {
|
pub fn curl_version() [*c]const u8 {
|
||||||
return libcurl.curl_version();
|
return libcurl.curl_version();
|
||||||
@@ -64,14 +54,13 @@ pub const Header = struct {
|
|||||||
|
|
||||||
pub const Headers = struct {
|
pub const Headers = struct {
|
||||||
headers: ?*libcurl.CurlSList,
|
headers: ?*libcurl.CurlSList,
|
||||||
cookies: ?[*c]const u8,
|
|
||||||
|
|
||||||
pub fn init(user_agent: [:0]const u8) !Headers {
|
pub fn init(user_agent: [:0]const u8) !Headers {
|
||||||
const header_list = libcurl.curl_slist_append(null, user_agent);
|
const header_list = libcurl.curl_slist_append(null, user_agent);
|
||||||
if (header_list == null) {
|
if (header_list == null) {
|
||||||
return error.OutOfMemory;
|
return error.OutOfMemory;
|
||||||
}
|
}
|
||||||
return .{ .headers = header_list, .cookies = null };
|
return .{ .headers = header_list };
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn deinit(self: *const Headers) void {
|
pub fn deinit(self: *const Headers) void {
|
||||||
@@ -102,20 +91,14 @@ pub const Headers = struct {
|
|||||||
pub fn iterator(self: *Headers) Iterator {
|
pub fn iterator(self: *Headers) Iterator {
|
||||||
return .{
|
return .{
|
||||||
.header = self.headers,
|
.header = self.headers,
|
||||||
.cookies = self.cookies,
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
const Iterator = struct {
|
const Iterator = struct {
|
||||||
header: [*c]libcurl.CurlSList,
|
header: [*c]libcurl.CurlSList,
|
||||||
cookies: ?[*c]const u8,
|
|
||||||
|
|
||||||
pub fn next(self: *Iterator) ?Header {
|
pub fn next(self: *Iterator) ?Header {
|
||||||
const h = self.header orelse {
|
const h = self.header orelse return null;
|
||||||
const cookies = self.cookies orelse return null;
|
|
||||||
self.cookies = null;
|
|
||||||
return .{ .name = "Cookie", .value = std.mem.span(@as([*:0]const u8, cookies)) };
|
|
||||||
};
|
|
||||||
|
|
||||||
self.header = h.*.next;
|
self.header = h.*.next;
|
||||||
return parseHeader(std.mem.span(@as([*:0]const u8, @ptrCast(h.*.data))));
|
return parseHeader(std.mem.span(@as([*:0]const u8, @ptrCast(h.*.data))));
|
||||||
@@ -142,7 +125,7 @@ pub const HeaderIterator = union(enum) {
|
|||||||
prev: ?*libcurl.CurlHeader = null,
|
prev: ?*libcurl.CurlHeader = null,
|
||||||
|
|
||||||
pub fn next(self: *CurlHeaderIterator) ?Header {
|
pub fn next(self: *CurlHeaderIterator) ?Header {
|
||||||
const h = libcurl.curl_easy_nextheader(self.conn.easy, .header, -1, self.prev) orelse return null;
|
const h = libcurl.curl_easy_nextheader(self.conn._easy, .header, -1, self.prev) orelse return null;
|
||||||
self.prev = h;
|
self.prev = h;
|
||||||
|
|
||||||
const header = h.*;
|
const header = h.*;
|
||||||
@@ -174,33 +157,24 @@ const HeaderValue = struct {
|
|||||||
};
|
};
|
||||||
|
|
||||||
pub const AuthChallenge = struct {
|
pub const AuthChallenge = struct {
|
||||||
|
const Source = enum { server, proxy };
|
||||||
|
const Scheme = enum { basic, digest };
|
||||||
|
|
||||||
status: u16,
|
status: u16,
|
||||||
source: ?enum { server, proxy },
|
source: ?Source,
|
||||||
scheme: ?enum { basic, digest },
|
scheme: ?Scheme,
|
||||||
realm: ?[]const u8,
|
realm: ?[]const u8,
|
||||||
|
|
||||||
pub fn parse(status: u16, header: []const u8) !AuthChallenge {
|
pub fn parse(status: u16, source: Source, value: []const u8) !AuthChallenge {
|
||||||
var ac: AuthChallenge = .{
|
var ac: AuthChallenge = .{
|
||||||
.status = status,
|
.status = status,
|
||||||
.source = null,
|
.source = source,
|
||||||
.realm = null,
|
.realm = null,
|
||||||
.scheme = null,
|
.scheme = null,
|
||||||
};
|
};
|
||||||
|
|
||||||
const sep = std.mem.indexOfPos(u8, header, 0, ": ") orelse return error.InvalidHeader;
|
const pos = std.mem.indexOfPos(u8, std.mem.trim(u8, value, std.ascii.whitespace[0..]), 0, " ") orelse value.len;
|
||||||
const hname = header[0..sep];
|
const _scheme = value[0..pos];
|
||||||
const hvalue = header[sep + 2 ..];
|
|
||||||
|
|
||||||
if (std.ascii.eqlIgnoreCase("WWW-Authenticate", hname)) {
|
|
||||||
ac.source = .server;
|
|
||||||
} else if (std.ascii.eqlIgnoreCase("Proxy-Authenticate", hname)) {
|
|
||||||
ac.source = .proxy;
|
|
||||||
} else {
|
|
||||||
return error.InvalidAuthChallenge;
|
|
||||||
}
|
|
||||||
|
|
||||||
const pos = std.mem.indexOfPos(u8, std.mem.trim(u8, hvalue, std.ascii.whitespace[0..]), 0, " ") orelse hvalue.len;
|
|
||||||
const _scheme = hvalue[0..pos];
|
|
||||||
if (std.ascii.eqlIgnoreCase(_scheme, "basic")) {
|
if (std.ascii.eqlIgnoreCase(_scheme, "basic")) {
|
||||||
ac.scheme = .basic;
|
ac.scheme = .basic;
|
||||||
} else if (std.ascii.eqlIgnoreCase(_scheme, "digest")) {
|
} else if (std.ascii.eqlIgnoreCase(_scheme, "digest")) {
|
||||||
@@ -236,77 +210,28 @@ pub const ResponseHead = struct {
|
|||||||
};
|
};
|
||||||
|
|
||||||
pub const Connection = struct {
|
pub const Connection = struct {
|
||||||
easy: *libcurl.Curl,
|
_easy: *libcurl.Curl,
|
||||||
node: std.DoublyLinkedList.Node = .{},
|
node: std.DoublyLinkedList.Node = .{},
|
||||||
|
|
||||||
pub fn init(
|
pub fn init(
|
||||||
ca_blob_: ?libcurl.CurlBlob,
|
ca_blob: ?libcurl.CurlBlob,
|
||||||
config: *const Config,
|
config: *const Config,
|
||||||
) !Connection {
|
) !Connection {
|
||||||
const easy = libcurl.curl_easy_init() orelse return error.FailedToInitializeEasy;
|
const easy = libcurl.curl_easy_init() orelse return error.FailedToInitializeEasy;
|
||||||
errdefer libcurl.curl_easy_cleanup(easy);
|
|
||||||
|
|
||||||
// timeouts
|
const self = Connection{ ._easy = easy };
|
||||||
try libcurl.curl_easy_setopt(easy, .timeout_ms, config.httpTimeout());
|
errdefer self.deinit();
|
||||||
try libcurl.curl_easy_setopt(easy, .connect_timeout_ms, config.httpConnectTimeout());
|
|
||||||
|
|
||||||
// redirect behavior
|
try self.reset(config, ca_blob);
|
||||||
try libcurl.curl_easy_setopt(easy, .max_redirs, config.httpMaxRedirects());
|
return self;
|
||||||
try libcurl.curl_easy_setopt(easy, .follow_location, 2);
|
|
||||||
try libcurl.curl_easy_setopt(easy, .redir_protocols_str, "HTTP,HTTPS"); // remove FTP and FTPS from the default
|
|
||||||
|
|
||||||
// proxy
|
|
||||||
const http_proxy = config.httpProxy();
|
|
||||||
if (http_proxy) |proxy| {
|
|
||||||
try libcurl.curl_easy_setopt(easy, .proxy, proxy.ptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
// tls
|
|
||||||
if (ca_blob_) |ca_blob| {
|
|
||||||
try libcurl.curl_easy_setopt(easy, .ca_info_blob, ca_blob);
|
|
||||||
if (http_proxy != null) {
|
|
||||||
try libcurl.curl_easy_setopt(easy, .proxy_ca_info_blob, ca_blob);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
assert(config.tlsVerifyHost() == false, "Http.init tls_verify_host", .{});
|
|
||||||
|
|
||||||
try libcurl.curl_easy_setopt(easy, .ssl_verify_host, false);
|
|
||||||
try libcurl.curl_easy_setopt(easy, .ssl_verify_peer, false);
|
|
||||||
|
|
||||||
if (http_proxy != null) {
|
|
||||||
try libcurl.curl_easy_setopt(easy, .proxy_ssl_verify_host, false);
|
|
||||||
try libcurl.curl_easy_setopt(easy, .proxy_ssl_verify_peer, false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// compression, don't remove this. CloudFront will send gzip content
|
|
||||||
// even if we don't support it, and then it won't be decompressed.
|
|
||||||
// empty string means: use whatever's available
|
|
||||||
try libcurl.curl_easy_setopt(easy, .accept_encoding, "");
|
|
||||||
|
|
||||||
// debug
|
|
||||||
if (comptime ENABLE_DEBUG) {
|
|
||||||
try libcurl.curl_easy_setopt(easy, .verbose, true);
|
|
||||||
|
|
||||||
// Sometimes the default debug output hides some useful data. You can
|
|
||||||
// uncomment the following line (BUT KEEP THE LIVE ABOVE AS-IS), to
|
|
||||||
// get more control over the data (specifically, the `CURLINFO_TEXT`
|
|
||||||
// can include useful data).
|
|
||||||
|
|
||||||
// try libcurl.curl_easy_setopt(easy, .debug_function, debugCallback);
|
|
||||||
}
|
|
||||||
|
|
||||||
return .{
|
|
||||||
.easy = easy,
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn deinit(self: *const Connection) void {
|
pub fn deinit(self: *const Connection) void {
|
||||||
libcurl.curl_easy_cleanup(self.easy);
|
libcurl.curl_easy_cleanup(self._easy);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn setURL(self: *const Connection, url: [:0]const u8) !void {
|
pub fn setURL(self: *const Connection, url: [:0]const u8) !void {
|
||||||
try libcurl.curl_easy_setopt(self.easy, .url, url.ptr);
|
try libcurl.curl_easy_setopt(self._easy, .url, url.ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
// a libcurl request has 2 methods. The first is the method that
|
// a libcurl request has 2 methods. The first is the method that
|
||||||
@@ -329,7 +254,7 @@ pub const Connection = struct {
|
|||||||
// can infer that based on the presence of the body, but we also reset it
|
// can infer that based on the presence of the body, but we also reset it
|
||||||
// to be safe);
|
// to be safe);
|
||||||
pub fn setMethod(self: *const Connection, method: Method) !void {
|
pub fn setMethod(self: *const Connection, method: Method) !void {
|
||||||
const easy = self.easy;
|
const easy = self._easy;
|
||||||
const m: [:0]const u8 = switch (method) {
|
const m: [:0]const u8 = switch (method) {
|
||||||
.GET => "GET",
|
.GET => "GET",
|
||||||
.POST => "POST",
|
.POST => "POST",
|
||||||
@@ -344,56 +269,97 @@ pub const Connection = struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn setBody(self: *const Connection, body: []const u8) !void {
|
pub fn setBody(self: *const Connection, body: []const u8) !void {
|
||||||
const easy = self.easy;
|
const easy = self._easy;
|
||||||
try libcurl.curl_easy_setopt(easy, .post, true);
|
try libcurl.curl_easy_setopt(easy, .post, true);
|
||||||
try libcurl.curl_easy_setopt(easy, .post_field_size, body.len);
|
try libcurl.curl_easy_setopt(easy, .post_field_size, body.len);
|
||||||
try libcurl.curl_easy_setopt(easy, .copy_post_fields, body.ptr);
|
try libcurl.curl_easy_setopt(easy, .copy_post_fields, body.ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn setGetMode(self: *const Connection) !void {
|
pub fn setGetMode(self: *const Connection) !void {
|
||||||
try libcurl.curl_easy_setopt(self.easy, .http_get, true);
|
try libcurl.curl_easy_setopt(self._easy, .http_get, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn setHeaders(self: *const Connection, headers: *Headers) !void {
|
pub fn setHeaders(self: *const Connection, headers: *Headers) !void {
|
||||||
try libcurl.curl_easy_setopt(self.easy, .http_header, headers.headers);
|
try libcurl.curl_easy_setopt(self._easy, .http_header, headers.headers);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn setCookies(self: *const Connection, cookies: [*c]const u8) !void {
|
pub fn setCookies(self: *const Connection, cookies: [*c]const u8) !void {
|
||||||
try libcurl.curl_easy_setopt(self.easy, .cookie, cookies);
|
try libcurl.curl_easy_setopt(self._easy, .cookie, cookies);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn setPrivate(self: *const Connection, ptr: *anyopaque) !void {
|
pub fn setPrivate(self: *const Connection, ptr: *anyopaque) !void {
|
||||||
try libcurl.curl_easy_setopt(self.easy, .private, ptr);
|
try libcurl.curl_easy_setopt(self._easy, .private, ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn setProxyCredentials(self: *const Connection, creds: [:0]const u8) !void {
|
pub fn setProxyCredentials(self: *const Connection, creds: [:0]const u8) !void {
|
||||||
try libcurl.curl_easy_setopt(self.easy, .proxy_user_pwd, creds.ptr);
|
try libcurl.curl_easy_setopt(self._easy, .proxy_user_pwd, creds.ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn setCredentials(self: *const Connection, creds: [:0]const u8) !void {
|
pub fn setCredentials(self: *const Connection, creds: [:0]const u8) !void {
|
||||||
try libcurl.curl_easy_setopt(self.easy, .user_pwd, creds.ptr);
|
try libcurl.curl_easy_setopt(self._easy, .user_pwd, creds.ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn setCallbacks(
|
pub fn setCallbacks(
|
||||||
self: *const Connection,
|
self: *Connection,
|
||||||
comptime header_cb: libcurl.CurlHeaderFunction,
|
|
||||||
comptime data_cb: libcurl.CurlWriteFunction,
|
comptime data_cb: libcurl.CurlWriteFunction,
|
||||||
) !void {
|
) !void {
|
||||||
try libcurl.curl_easy_setopt(self.easy, .header_data, self.easy);
|
try libcurl.curl_easy_setopt(self._easy, .write_data, self);
|
||||||
try libcurl.curl_easy_setopt(self.easy, .header_function, header_cb);
|
try libcurl.curl_easy_setopt(self._easy, .write_function, data_cb);
|
||||||
try libcurl.curl_easy_setopt(self.easy, .write_data, self.easy);
|
|
||||||
try libcurl.curl_easy_setopt(self.easy, .write_function, data_cb);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn reset(self: *const Connection) !void {
|
pub fn reset(
|
||||||
try libcurl.curl_easy_setopt(self.easy, .proxy, null);
|
self: *const Connection,
|
||||||
try libcurl.curl_easy_setopt(self.easy, .http_header, null);
|
config: *const Config,
|
||||||
|
ca_blob: ?libcurl.CurlBlob,
|
||||||
|
) !void {
|
||||||
|
libcurl.curl_easy_reset(self._easy);
|
||||||
|
|
||||||
try libcurl.curl_easy_setopt(self.easy, .header_data, null);
|
// timeouts
|
||||||
try libcurl.curl_easy_setopt(self.easy, .header_function, null);
|
try libcurl.curl_easy_setopt(self._easy, .timeout_ms, config.httpTimeout());
|
||||||
|
try libcurl.curl_easy_setopt(self._easy, .connect_timeout_ms, config.httpConnectTimeout());
|
||||||
|
|
||||||
try libcurl.curl_easy_setopt(self.easy, .write_data, null);
|
// compression, don't remove this. CloudFront will send gzip content
|
||||||
try libcurl.curl_easy_setopt(self.easy, .write_function, discardBody);
|
// even if we don't support it, and then it won't be decompressed.
|
||||||
|
// empty string means: use whatever's available
|
||||||
|
try libcurl.curl_easy_setopt(self._easy, .accept_encoding, "");
|
||||||
|
|
||||||
|
// proxy
|
||||||
|
const http_proxy = config.httpProxy();
|
||||||
|
if (http_proxy) |proxy| {
|
||||||
|
try libcurl.curl_easy_setopt(self._easy, .proxy, proxy.ptr);
|
||||||
|
} else {
|
||||||
|
try libcurl.curl_easy_setopt(self._easy, .proxy, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
// tls
|
||||||
|
if (ca_blob) |ca| {
|
||||||
|
try libcurl.curl_easy_setopt(self._easy, .ca_info_blob, ca);
|
||||||
|
if (http_proxy != null) {
|
||||||
|
try libcurl.curl_easy_setopt(self._easy, .proxy_ca_info_blob, ca);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
assert(config.tlsVerifyHost() == false, "Http.init tls_verify_host", .{});
|
||||||
|
|
||||||
|
try libcurl.curl_easy_setopt(self._easy, .ssl_verify_host, false);
|
||||||
|
try libcurl.curl_easy_setopt(self._easy, .ssl_verify_peer, false);
|
||||||
|
|
||||||
|
if (http_proxy != null) {
|
||||||
|
try libcurl.curl_easy_setopt(self._easy, .proxy_ssl_verify_host, false);
|
||||||
|
try libcurl.curl_easy_setopt(self._easy, .proxy_ssl_verify_peer, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// debug
|
||||||
|
if (comptime ENABLE_DEBUG) {
|
||||||
|
try libcurl.curl_easy_setopt(self._easy, .verbose, true);
|
||||||
|
|
||||||
|
// Sometimes the default debug output hides some useful data. You can
|
||||||
|
// uncomment the following line (BUT KEEP THE LIVE ABOVE AS-IS), to
|
||||||
|
// get more control over the data (specifically, the `CURLINFO_TEXT`
|
||||||
|
// can include useful data).
|
||||||
|
|
||||||
|
// try libcurl.curl_easy_setopt(easy, .debug_function, debugCallback);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn discardBody(_: [*]const u8, count: usize, len: usize, _: ?*anyopaque) usize {
|
fn discardBody(_: [*]const u8, count: usize, len: usize, _: ?*anyopaque) usize {
|
||||||
@@ -401,27 +367,31 @@ pub const Connection = struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn setProxy(self: *const Connection, proxy: ?[:0]const u8) !void {
|
pub fn setProxy(self: *const Connection, proxy: ?[:0]const u8) !void {
|
||||||
try libcurl.curl_easy_setopt(self.easy, .proxy, if (proxy) |p| p.ptr else null);
|
try libcurl.curl_easy_setopt(self._easy, .proxy, if (proxy) |p| p.ptr else null);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn setFollowLocation(self: *const Connection, follow: bool) !void {
|
||||||
|
try libcurl.curl_easy_setopt(self._easy, .follow_location, @as(c_long, if (follow) 2 else 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn setTlsVerify(self: *const Connection, verify: bool, use_proxy: bool) !void {
|
pub fn setTlsVerify(self: *const Connection, verify: bool, use_proxy: bool) !void {
|
||||||
try libcurl.curl_easy_setopt(self.easy, .ssl_verify_host, verify);
|
try libcurl.curl_easy_setopt(self._easy, .ssl_verify_host, verify);
|
||||||
try libcurl.curl_easy_setopt(self.easy, .ssl_verify_peer, verify);
|
try libcurl.curl_easy_setopt(self._easy, .ssl_verify_peer, verify);
|
||||||
if (use_proxy) {
|
if (use_proxy) {
|
||||||
try libcurl.curl_easy_setopt(self.easy, .proxy_ssl_verify_host, verify);
|
try libcurl.curl_easy_setopt(self._easy, .proxy_ssl_verify_host, verify);
|
||||||
try libcurl.curl_easy_setopt(self.easy, .proxy_ssl_verify_peer, verify);
|
try libcurl.curl_easy_setopt(self._easy, .proxy_ssl_verify_peer, verify);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn getEffectiveUrl(self: *const Connection) ![*c]const u8 {
|
pub fn getEffectiveUrl(self: *const Connection) ![*c]const u8 {
|
||||||
var url: [*c]u8 = undefined;
|
var url: [*c]u8 = undefined;
|
||||||
try libcurl.curl_easy_getinfo(self.easy, .effective_url, &url);
|
try libcurl.curl_easy_getinfo(self._easy, .effective_url, &url);
|
||||||
return url;
|
return url;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn getResponseCode(self: *const Connection) !u16 {
|
pub fn getResponseCode(self: *const Connection) !u16 {
|
||||||
var status: c_long = undefined;
|
var status: c_long = undefined;
|
||||||
try libcurl.curl_easy_getinfo(self.easy, .response_code, &status);
|
try libcurl.curl_easy_getinfo(self._easy, .response_code, &status);
|
||||||
if (status < 0 or status > std.math.maxInt(u16)) {
|
if (status < 0 or status > std.math.maxInt(u16)) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -430,13 +400,13 @@ pub const Connection = struct {
|
|||||||
|
|
||||||
pub fn getRedirectCount(self: *const Connection) !u32 {
|
pub fn getRedirectCount(self: *const Connection) !u32 {
|
||||||
var count: c_long = undefined;
|
var count: c_long = undefined;
|
||||||
try libcurl.curl_easy_getinfo(self.easy, .redirect_count, &count);
|
try libcurl.curl_easy_getinfo(self._easy, .redirect_count, &count);
|
||||||
return @intCast(count);
|
return @intCast(count);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn getResponseHeader(self: *const Connection, name: [:0]const u8, index: usize) ?HeaderValue {
|
pub fn getResponseHeader(self: *const Connection, name: [:0]const u8, index: usize) ?HeaderValue {
|
||||||
var hdr: ?*libcurl.CurlHeader = null;
|
var hdr: ?*libcurl.CurlHeader = null;
|
||||||
libcurl.curl_easy_header(self.easy, name, index, .header, -1, &hdr) catch |err| {
|
libcurl.curl_easy_header(self._easy, name, index, .header, -1, &hdr) catch |err| {
|
||||||
// ErrorHeader includes OutOfMemory — rare but real errors from curl internals.
|
// ErrorHeader includes OutOfMemory — rare but real errors from curl internals.
|
||||||
// Logged and returned as null since callers don't expect errors.
|
// Logged and returned as null since callers don't expect errors.
|
||||||
log.err(.http, "get response header", .{
|
log.err(.http, "get response header", .{
|
||||||
@@ -454,7 +424,7 @@ pub const Connection = struct {
|
|||||||
|
|
||||||
pub fn getPrivate(self: *const Connection) !*anyopaque {
|
pub fn getPrivate(self: *const Connection) !*anyopaque {
|
||||||
var private: *anyopaque = undefined;
|
var private: *anyopaque = undefined;
|
||||||
try libcurl.curl_easy_getinfo(self.easy, .private, &private);
|
try libcurl.curl_easy_getinfo(self._easy, .private, &private);
|
||||||
return private;
|
return private;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -471,12 +441,7 @@ pub const Connection = struct {
|
|||||||
try self.secretHeaders(&header_list, http_headers);
|
try self.secretHeaders(&header_list, http_headers);
|
||||||
try self.setHeaders(&header_list);
|
try self.setHeaders(&header_list);
|
||||||
|
|
||||||
// Add cookies.
|
try libcurl.curl_easy_perform(self._easy);
|
||||||
if (header_list.cookies) |cookies| {
|
|
||||||
try self.setCookies(cookies);
|
|
||||||
}
|
|
||||||
|
|
||||||
try libcurl.curl_easy_perform(self.easy);
|
|
||||||
return self.getResponseCode();
|
return self.getResponseCode();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -498,11 +463,11 @@ pub const Handles = struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn add(self: *Handles, conn: *const Connection) !void {
|
pub fn add(self: *Handles, conn: *const Connection) !void {
|
||||||
try libcurl.curl_multi_add_handle(self.multi, conn.easy);
|
try libcurl.curl_multi_add_handle(self.multi, conn._easy);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn remove(self: *Handles, conn: *const Connection) !void {
|
pub fn remove(self: *Handles, conn: *const Connection) !void {
|
||||||
try libcurl.curl_multi_remove_handle(self.multi, conn.easy);
|
try libcurl.curl_multi_remove_handle(self.multi, conn._easy);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn perform(self: *Handles) !c_int {
|
pub fn perform(self: *Handles) !c_int {
|
||||||
@@ -525,7 +490,7 @@ pub const Handles = struct {
|
|||||||
const msg = libcurl.curl_multi_info_read(self.multi, &messages_count) orelse return null;
|
const msg = libcurl.curl_multi_info_read(self.multi, &messages_count) orelse return null;
|
||||||
return switch (msg.data) {
|
return switch (msg.data) {
|
||||||
.done => |err| .{
|
.done => |err| .{
|
||||||
.conn = .{ .easy = msg.easy_handle },
|
.conn = .{ ._easy = msg.easy_handle },
|
||||||
.err = err,
|
.err = err,
|
||||||
},
|
},
|
||||||
else => unreachable,
|
else => unreachable,
|
||||||
|
|||||||
@@ -516,6 +516,10 @@ pub fn curl_easy_cleanup(easy: *Curl) void {
|
|||||||
c.curl_easy_cleanup(easy);
|
c.curl_easy_cleanup(easy);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn curl_easy_reset(easy: *Curl) void {
|
||||||
|
c.curl_easy_reset(easy);
|
||||||
|
}
|
||||||
|
|
||||||
pub fn curl_easy_perform(easy: *Curl) Error!void {
|
pub fn curl_easy_perform(easy: *Curl) Error!void {
|
||||||
try errorCheck(c.curl_easy_perform(easy));
|
try errorCheck(c.curl_easy_perform(easy));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,7 +9,6 @@ const App = @import("../App.zig");
|
|||||||
const Config = @import("../Config.zig");
|
const Config = @import("../Config.zig");
|
||||||
const telemetry = @import("telemetry.zig");
|
const telemetry = @import("telemetry.zig");
|
||||||
const Runtime = @import("../network/Runtime.zig");
|
const Runtime = @import("../network/Runtime.zig");
|
||||||
const Connection = @import("../network/http.zig").Connection;
|
|
||||||
|
|
||||||
const URL = "https://telemetry.lightpanda.io";
|
const URL = "https://telemetry.lightpanda.io";
|
||||||
const BUFFER_SIZE = 1024;
|
const BUFFER_SIZE = 1024;
|
||||||
|
|||||||
Reference in New Issue
Block a user