Merge pull request #529 from lightpanda-io/document-cookie
Some checks failed
e2e-test / zig build release (push) Has been cancelled
wpt / web platform tests (push) Has been cancelled
wpt / web platform tests json output (push) Has been cancelled
zig-test / zig build dev (push) Has been cancelled
zig-test / zig test (push) Has been cancelled
e2e-test / puppeteer-perf (push) Has been cancelled
e2e-test / demo-scripts (push) Has been cancelled
wpt / perf-fmt (push) Has been cancelled
zig-test / browser fetch (push) Has been cancelled
zig-test / perf-fmt (push) Has been cancelled
nightly build / build-linux-x86_64 (push) Has been cancelled
nightly build / build-linux-aarch64 (push) Has been cancelled
nightly build / build-macos-aarch64 (push) Has been cancelled
nightly build / build-macos-x86_64 (push) Has been cancelled

Document cookie
This commit is contained in:
Karl Seguin
2025-04-11 23:34:44 +08:00
committed by GitHub
2 changed files with 39 additions and 21 deletions

View File

@@ -33,6 +33,9 @@ const Location = @import("location.zig").Location;
const collection = @import("../dom/html_collection.zig");
const Walker = @import("../dom/walker.zig").WalkerDepthFirst;
const UserContext = @import("../user_context.zig").UserContext;
const Cookie = @import("../storage/cookie.zig").Cookie;
// WEB IDL https://html.spec.whatwg.org/#the-document-object
pub const HTMLDocument = struct {
pub const Self = parser.DocumentHTML;
@@ -81,14 +84,21 @@ pub const HTMLDocument = struct {
}
}
// TODO: not implemented by libdom
pub fn get_cookie(_: *parser.DocumentHTML) ![]const u8 {
return error.NotImplemented;
pub fn get_cookie(_: *parser.DocumentHTML, arena: std.mem.Allocator, userctx: UserContext) ![]const u8 {
var buf: std.ArrayListUnmanaged(u8) = .{};
try userctx.cookie_jar.forRequest(&userctx.url.uri, buf.writer(arena), .{ .navigation = true });
return buf.items;
}
// TODO: not implemented by libdom
pub fn set_cookie(_: *parser.DocumentHTML, _: []const u8) ![]const u8 {
return error.NotImplemented;
pub fn set_cookie(_: *parser.DocumentHTML, userctx: UserContext, cookie_str: []const u8) ![]const u8 {
// we use the cookie jar's allocator to parse the cookie because it
// outlives the page's arena.
const c = try Cookie.parse(userctx.cookie_jar.allocator, &userctx.url.uri, cookie_str);
errdefer c.deinit();
try userctx.cookie_jar.add(c, std.time.timestamp());
return cookie_str;
}
pub fn get_title(self: *parser.DocumentHTML) ![]const u8 {
@@ -258,4 +268,12 @@ pub fn testExecFn(
.{ .src = "list.length", .ex = "1" },
};
try checkCases(js_env, &getElementsByName);
var cookie = [_]Case{
.{ .src = "document.cookie", .ex = "" },
.{ .src = "document.cookie = 'name=Oeschger; SameSite=None; Secure'", .ex = "name=Oeschger; SameSite=None; Secure" },
.{ .src = "document.cookie = 'favorite_food=tripe; SameSite=None; Secure'", .ex = "favorite_food=tripe; SameSite=None; Secure" },
.{ .src = "document.cookie", .ex = "name=Oeschger; favorite_food=tripe" },
};
try checkCases(js_env, &cookie);
}

View File

@@ -145,7 +145,7 @@ pub const Jar = struct {
if (first) {
first = false;
} else {
try writer.writeAll(", ");
try writer.writeAll("; ");
}
try writeCookie(cookie, writer);
}
@@ -563,8 +563,8 @@ test "Jar: forRequest" {
try jar.add(try Cookie.parse(testing.allocator, &test_uri_2, "domain1=9;domain=test.lightpanda.io"), now);
// nothing fancy here
try expectCookies("global1=1, global2=2", &jar, test_uri, .{});
try expectCookies("global1=1, global2=2", &jar, test_uri, .{ .origin_uri = &test_uri, .navigation = false });
try expectCookies("global1=1; global2=2", &jar, test_uri, .{});
try expectCookies("global1=1; global2=2", &jar, test_uri, .{ .origin_uri = &test_uri, .navigation = false });
// We have a cookie where Domain=lightpanda.io
// This should _not_ match xyxlightpanda.io
@@ -573,47 +573,47 @@ test "Jar: forRequest" {
});
// matching path without trailing /
try expectCookies("global1=1, global2=2, path1=3", &jar, try std.Uri.parse("http://lightpanda.io/about"), .{
try expectCookies("global1=1; global2=2; path1=3", &jar, try std.Uri.parse("http://lightpanda.io/about"), .{
.origin_uri = &test_uri,
});
// incomplete prefix path
try expectCookies("global1=1, global2=2", &jar, try std.Uri.parse("http://lightpanda.io/abou"), .{
try expectCookies("global1=1; global2=2", &jar, try std.Uri.parse("http://lightpanda.io/abou"), .{
.origin_uri = &test_uri,
});
// path doesn't match
try expectCookies("global1=1, global2=2", &jar, try std.Uri.parse("http://lightpanda.io/aboutus"), .{
try expectCookies("global1=1; global2=2", &jar, try std.Uri.parse("http://lightpanda.io/aboutus"), .{
.origin_uri = &test_uri,
});
// path doesn't match cookie directory
try expectCookies("global1=1, global2=2", &jar, try std.Uri.parse("http://lightpanda.io/docs"), .{
try expectCookies("global1=1; global2=2", &jar, try std.Uri.parse("http://lightpanda.io/docs"), .{
.origin_uri = &test_uri,
});
// exact directory match
try expectCookies("global1=1, global2=2, path2=4", &jar, try std.Uri.parse("http://lightpanda.io/docs/"), .{
try expectCookies("global1=1; global2=2; path2=4", &jar, try std.Uri.parse("http://lightpanda.io/docs/"), .{
.origin_uri = &test_uri,
});
// sub directory match
try expectCookies("global1=1, global2=2, path2=4", &jar, try std.Uri.parse("http://lightpanda.io/docs/more"), .{
try expectCookies("global1=1; global2=2; path2=4", &jar, try std.Uri.parse("http://lightpanda.io/docs/more"), .{
.origin_uri = &test_uri,
});
// secure
try expectCookies("global1=1, global2=2, secure=5", &jar, try std.Uri.parse("https://lightpanda.io/"), .{
try expectCookies("global1=1; global2=2; secure=5", &jar, try std.Uri.parse("https://lightpanda.io/"), .{
.origin_uri = &test_uri,
});
// navigational cross domain, secure
try expectCookies("global1=1, global2=2, secure=5, sitenone=6, sitelax=7", &jar, try std.Uri.parse("https://lightpanda.io/x/"), .{
try expectCookies("global1=1; global2=2; secure=5; sitenone=6; sitelax=7", &jar, try std.Uri.parse("https://lightpanda.io/x/"), .{
.origin_uri = &(try std.Uri.parse("https://example.com/")),
});
// navigational cross domain, insecure
try expectCookies("global1=1, global2=2, sitelax=7", &jar, try std.Uri.parse("http://lightpanda.io/x/"), .{
try expectCookies("global1=1; global2=2; sitelax=7", &jar, try std.Uri.parse("http://lightpanda.io/x/"), .{
.origin_uri = &(try std.Uri.parse("https://example.com/")),
});
@@ -630,18 +630,18 @@ test "Jar: forRequest" {
});
// non-navigational same origin
try expectCookies("global1=1, global2=2, sitelax=7, sitestrict=8", &jar, try std.Uri.parse("http://lightpanda.io/x/"), .{
try expectCookies("global1=1; global2=2; sitelax=7; sitestrict=8", &jar, try std.Uri.parse("http://lightpanda.io/x/"), .{
.origin_uri = &(try std.Uri.parse("https://lightpanda.io/")),
.navigation = false,
});
// exact domain match + suffix
try expectCookies("global2=2, domain1=9", &jar, try std.Uri.parse("http://test.lightpanda.io/"), .{
try expectCookies("global2=2; domain1=9", &jar, try std.Uri.parse("http://test.lightpanda.io/"), .{
.origin_uri = &test_uri,
});
// domain suffix match + suffix
try expectCookies("global2=2, domain1=9", &jar, try std.Uri.parse("http://1.test.lightpanda.io/"), .{
try expectCookies("global2=2; domain1=9", &jar, try std.Uri.parse("http://1.test.lightpanda.io/"), .{
.origin_uri = &test_uri,
});