@@ -29,6 +29,7 @@ pub fn processMessage(cmd: anytype) !void {
2929 setCacheDisabled ,
3030 setExtraHTTPHeaders ,
3131 deleteCookies ,
32+ setCookie ,
3233 setCookies ,
3334 }, cmd .input .action ) orelse return error .UnknownMethod ;
3435
@@ -38,6 +39,7 @@ pub fn processMessage(cmd: anytype) !void {
3839 .setCacheDisabled = > return cmd .sendResult (null , .{}),
3940 .setExtraHTTPHeaders = > return setExtraHTTPHeaders (cmd ),
4041 .deleteCookies = > return deleteCookies (cmd ),
42+ .setCookie = > return setCookie (cmd ),
4143 .setCookies = > return setCookies (cmd ),
4244 }
4345}
@@ -168,60 +170,77 @@ fn percentEncodedDomain(allocator: Allocator, default_url: ?[]const u8, domain:
168170 } else return null ;
169171}
170172
173+ const CdpCookie = struct {
174+ name : []const u8 ,
175+ value : []const u8 ,
176+ url : ? []const u8 = null ,
177+ domain : ? []const u8 = null ,
178+ path : ? []const u8 = null ,
179+ secure : bool = false , // default: https://www.rfc-editor.org/rfc/rfc6265#section-5.3
180+ httpOnly : bool = false , // default: https://www.rfc-editor.org/rfc/rfc6265#section-5.3
181+ sameSite : SameSite = .None , // default: https://datatracker.ietf.org/doc/html/draft-west-first-party-cookies
182+ expires : ? i64 = null , // -1? says google
183+ priority : CookiePriority = .Medium , // default: https://datatracker.ietf.org/doc/html/draft-west-cookie-priority-00
184+ sameParty : ? bool = null ,
185+ sourceScheme : ? CookieSourceScheme = null ,
186+ // sourcePort: Temporary ability and it will be removed from CDP
187+ partitionKey : ? CookiePartitionKey = null ,
188+ };
189+
190+ fn setCookie (cmd : anytype ) ! void {
191+ const params = (try cmd .params (
192+ CdpCookie ,
193+ )) orelse return error .InvalidParams ;
194+
195+ const bc = cmd .browser_context orelse return error .BrowserContextNotLoaded ;
196+ try setCdpCookie (& bc .session .cookie_jar , params );
197+
198+ try cmd .sendResult (.{ .success = true }, .{});
199+ }
200+
171201fn setCookies (cmd : anytype ) ! void {
172202 const params = (try cmd .params (struct {
173- cookies : []const struct {
174- name : []const u8 ,
175- value : []const u8 ,
176- url : ? []const u8 = null ,
177- domain : ? []const u8 = null ,
178- path : ? []const u8 = null ,
179- secure : bool = false , // default: https://www.rfc-editor.org/rfc/rfc6265#section-5.3
180- httpOnly : bool = false , // default: https://www.rfc-editor.org/rfc/rfc6265#section-5.3
181- sameSite : SameSite = .None , // default: https://datatracker.ietf.org/doc/html/draft-west-first-party-cookies
182- expires : ? i64 = null , // -1? says google
183- priority : CookiePriority = .Medium , // default: https://datatracker.ietf.org/doc/html/draft-west-cookie-priority-00
184- sameParty : ? bool = null ,
185- sourceScheme : ? CookieSourceScheme = null ,
186- // sourcePort: Temporary ability and it will be removed from CDP
187- partitionKey : ? CookiePartitionKey = null ,
188- },
203+ cookies : []const CdpCookie ,
189204 })) orelse return error .InvalidParams ;
190205
191206 const bc = cmd .browser_context orelse return error .BrowserContextNotLoaded ;
192207 for (params .cookies ) | param | {
193- if (param .priority != .Medium or param .sameParty != null or param .sourceScheme != null or param .partitionKey != null ) {
194- return error .NotYetImplementedParams ;
195- }
196- if (param .name .len == 0 ) return error .InvalidParams ;
197- if (param .value .len == 0 ) return error .InvalidParams ;
198-
199- var arena = std .heap .ArenaAllocator .init (bc .session .cookie_jar .allocator );
200- errdefer arena .deinit ();
201- const a = arena .allocator ();
202-
203- // NOTE: The param.url can affect the default domain, path, source port, and source scheme.
204- const domain = try percentEncodedDomain (a , param .url , param .domain ) orelse return error .InvalidParams ;
205-
206- const cookie = Cookie {
207- .arena = arena ,
208- .name = try a .dupe (u8 , param .name ),
209- .value = try a .dupe (u8 , param .value ),
210- .path = if (param .path ) | path | try a .dupe (u8 , path ) else "/" , // Chrome does not actually take the path from the url and just defaults to "/".
211- .domain = domain ,
212- .expires = param .expires ,
213- .secure = param .secure ,
214- .http_only = param .httpOnly ,
215- .same_site = switch (param .sameSite ) {
216- .Strict = > .strict ,
217- .Lax = > .lax ,
218- .None = > .none ,
219- },
220- };
221- try bc .session .cookie_jar .add (cookie , std .time .timestamp ());
208+ try setCdpCookie (& bc .session .cookie_jar , param );
222209 }
223210
224- return cmd .sendResult (null , .{});
211+ try cmd .sendResult (null , .{});
212+ }
213+
214+ fn setCdpCookie (cookie_jar : * CookieJar , param : CdpCookie ) ! void {
215+ if (param .priority != .Medium or param .sameParty != null or param .sourceScheme != null or param .partitionKey != null ) {
216+ return error .NotYetImplementedParams ;
217+ }
218+ if (param .name .len == 0 ) return error .InvalidParams ;
219+ if (param .value .len == 0 ) return error .InvalidParams ;
220+
221+ var arena = std .heap .ArenaAllocator .init (cookie_jar .allocator );
222+ errdefer arena .deinit ();
223+ const a = arena .allocator ();
224+
225+ // NOTE: The param.url can affect the default domain, path, source port, and source scheme.
226+ const domain = try percentEncodedDomain (a , param .url , param .domain ) orelse return error .InvalidParams ;
227+
228+ const cookie = Cookie {
229+ .arena = arena ,
230+ .name = try a .dupe (u8 , param .name ),
231+ .value = try a .dupe (u8 , param .value ),
232+ .path = if (param .path ) | path | try a .dupe (u8 , path ) else "/" , // Chrome does not actually take the path from the url and just defaults to "/".
233+ .domain = domain ,
234+ .expires = param .expires ,
235+ .secure = param .secure ,
236+ .http_only = param .httpOnly ,
237+ .same_site = switch (param .sameSite ) {
238+ .Strict = > .strict ,
239+ .Lax = > .lax ,
240+ .None = > .none ,
241+ },
242+ };
243+ try cookie_jar .add (cookie , std .time .timestamp ());
225244}
226245
227246// Upsert a header into the headers array.
0 commit comments