mirror of
				https://github.com/lightpanda-io/browser.git
				synced 2025-10-29 15:13:28 +00:00 
			
		
		
		
	Emit http_request_fail notification
CDP translate this into a Network.loadingFailed. This is necessary to make sure every Network.requestWillBeSent is paired with either a Network.loadingFailed or a Network.responseReceived.
This commit is contained in:
		| @@ -247,6 +247,8 @@ pub const Page = struct { | ||||
|                 .content_type = content_type, | ||||
|                 .charset = mime.charset, | ||||
|                 .url = request_url, | ||||
|                 .method = opts.method, | ||||
|                 .reason = opts.reason, | ||||
|             }); | ||||
|  | ||||
|             if (!mime.isHTML()) { | ||||
| @@ -597,6 +599,10 @@ pub const Page = struct { | ||||
|     // The page.arena is safe to use here, but the transfer_arena exists | ||||
|     // specifically for this type of lifetime. | ||||
|     pub fn navigateFromWebAPI(self: *Page, url: []const u8, opts: NavigateOpts) !void { | ||||
|         log.debug(.browser, "delayed navigation", .{ | ||||
|             .url = url, | ||||
|             .reason = opts.reason, | ||||
|         }); | ||||
|         self.delayed_navigation = true; | ||||
|         const arena = self.session.transfer_arena; | ||||
|         const navi = try arena.create(DelayedNavigation); | ||||
|   | ||||
| @@ -338,7 +338,11 @@ pub const XMLHttpRequest = struct { | ||||
|     // dispatch request event. | ||||
|     // errors are logged only. | ||||
|     fn dispatchEvt(self: *XMLHttpRequest, typ: []const u8) void { | ||||
|         log.debug(.script_event, "dispatch event", .{ .type = typ, .source = "xhr" }); | ||||
|         log.debug(.script_event, "dispatch event", .{ | ||||
|             .type = typ, | ||||
|             .source = "xhr", | ||||
|             .url = self.url, | ||||
|         }); | ||||
|         self._dispatchEvt(typ) catch |err| { | ||||
|             log.err(.app, "dispatch event error", .{ .err = err, .type = typ, .source = "xhr" }); | ||||
|         }; | ||||
| @@ -358,7 +362,11 @@ pub const XMLHttpRequest = struct { | ||||
|         typ: []const u8, | ||||
|         opts: ProgressEvent.EventInit, | ||||
|     ) void { | ||||
|         log.debug(.script_event, "dispatch progress event", .{ .type = typ, .source = "xhr" }); | ||||
|         log.debug(.script_event, "dispatch progress event", .{ | ||||
|             .type = typ, | ||||
|             .source = "xhr", | ||||
|             .url = self.url, | ||||
|         }); | ||||
|         self._dispatchProgressEvent(typ, opts) catch |err| { | ||||
|             log.err(.app, "dispatch progress event error", .{ .err = err, .type = typ, .source = "xhr" }); | ||||
|         }; | ||||
|   | ||||
| @@ -412,11 +412,13 @@ pub fn BrowserContext(comptime CDP_T: type) type { | ||||
|         } | ||||
|  | ||||
|         pub fn networkEnable(self: *Self) !void { | ||||
|             try self.cdp.browser.notification.register(.http_request_fail, self, onHttpRequestFail); | ||||
|             try self.cdp.browser.notification.register(.http_request_start, self, onHttpRequestStart); | ||||
|             try self.cdp.browser.notification.register(.http_request_complete, self, onHttpRequestComplete); | ||||
|         } | ||||
|  | ||||
|         pub fn networkDisable(self: *Self) void { | ||||
|             self.cdp.browser.notification.unregister(.http_request_fail, self); | ||||
|             self.cdp.browser.notification.unregister(.http_request_start, self); | ||||
|             self.cdp.browser.notification.unregister(.http_request_complete, self); | ||||
|         } | ||||
| @@ -448,6 +450,12 @@ pub fn BrowserContext(comptime CDP_T: type) type { | ||||
|             return @import("domains/network.zig").httpRequestStart(self.notification_arena, self, data); | ||||
|         } | ||||
|  | ||||
|         pub fn onHttpRequestFail(ctx: *anyopaque, data: *const Notification.RequestFail) !void { | ||||
|             const self: *Self = @alignCast(@ptrCast(ctx)); | ||||
|             defer self.resetNotificationArena(); | ||||
|             return @import("domains/network.zig").httpRequestFail(self.notification_arena, self, data); | ||||
|         } | ||||
|  | ||||
|         pub fn onHttpRequestComplete(ctx: *anyopaque, data: *const Notification.RequestComplete) !void { | ||||
|             const self: *Self = @alignCast(@ptrCast(ctx)); | ||||
|             defer self.resetNotificationArena(); | ||||
|   | ||||
| @@ -84,6 +84,24 @@ fn putAssumeCapacity(headers: *std.ArrayListUnmanaged(std.http.Header), extra: s | ||||
|     return true; | ||||
| } | ||||
|  | ||||
| pub fn httpRequestFail(arena: Allocator, bc: anytype, request: *const Notification.RequestFail) !void { | ||||
|     // Isn't possible to do a network request within a Browser (which our | ||||
|     // notification is tied to), without a page. | ||||
|     std.debug.assert(bc.session.page != null); | ||||
|  | ||||
|     // all unreachable because we _have_ to have a page. | ||||
|     const session_id = bc.session_id orelse unreachable; | ||||
|  | ||||
|     // We're missing a bunch of fields, but, for now, this seems like enough | ||||
|     try bc.cdp.sendEvent("Network.loadingFailed", .{ | ||||
|         .requestId = try std.fmt.allocPrint(arena, "REQ-{d}", .{request.id}), | ||||
|         // Seems to be what chrome answers with. I assume it depends on the type of error? | ||||
|         .type = "Ping", | ||||
|         .errorText = request.err, | ||||
|         .canceled = false, | ||||
|     }, .{ .session_id = session_id }); | ||||
| } | ||||
|  | ||||
| pub fn httpRequestStart(arena: Allocator, bc: anytype, request: *const Notification.RequestStart) !void { | ||||
|     // Isn't possible to do a network request within a Browser (which our | ||||
|     // notification is tied to), without a page. | ||||
|   | ||||
| @@ -354,6 +354,7 @@ pub const Request = struct { | ||||
|     // Because of things like redirects and error handling, it is possible for | ||||
|     // the notification functions to be called multiple times, so we guard them | ||||
|     // with these booleans | ||||
|     _notified_fail: bool, | ||||
|     _notified_start: bool, | ||||
|     _notified_complete: bool, | ||||
|  | ||||
| @@ -414,6 +415,7 @@ pub const Request = struct { | ||||
|             ._keepalive = false, | ||||
|             ._redirect_count = 0, | ||||
|             ._has_host_header = false, | ||||
|             ._notified_fail = false, | ||||
|             ._notified_start = false, | ||||
|             ._notified_complete = false, | ||||
|             ._connection_from_keepalive = false, | ||||
| @@ -428,6 +430,7 @@ pub const Request = struct { | ||||
|     } | ||||
|  | ||||
|     pub fn abort(self: *Request) void { | ||||
|         self.requestFailed("aborted"); | ||||
|         const aborter = self._aborter orelse { | ||||
|             self.deinit(); | ||||
|             return; | ||||
| @@ -555,6 +558,10 @@ pub const Request = struct { | ||||
|     } | ||||
|  | ||||
|     fn doSendSync(self: *Request, use_pool: bool) anyerror!Response { | ||||
|         // https://github.com/ziglang/zig/issues/20369 | ||||
|         // errdefer |err| self.requestFailed(@errorName(err)); | ||||
|         errdefer self.requestFailed("network error"); | ||||
|  | ||||
|         if (use_pool) { | ||||
|             if (self.findExistingConnection(true)) |connection| { | ||||
|                 self._connection = connection; | ||||
| @@ -847,6 +854,19 @@ pub const Request = struct { | ||||
|         }); | ||||
|     } | ||||
|  | ||||
|     fn requestFailed(self: *Request, err: []const u8) void { | ||||
|         const notification = self.notification orelse return; | ||||
|         if (self._notified_fail) { | ||||
|             return; | ||||
|         } | ||||
|         self._notified_fail = true; | ||||
|         notification.dispatch(.http_request_fail, &.{ | ||||
|             .id = self.id, | ||||
|             .err = err, | ||||
|             .url = self.request_uri, | ||||
|         }); | ||||
|     } | ||||
|  | ||||
|     fn requestCompleted(self: *Request, response: ResponseHeader) void { | ||||
|         const notification = self.notification orelse return; | ||||
|         if (self._notified_complete) { | ||||
| @@ -1290,6 +1310,8 @@ fn AsyncHandler(comptime H: type, comptime L: type) type { | ||||
|             self.handler.onHttpResponse(err) catch {}; | ||||
|             // just to be safe | ||||
|             self.request._keepalive = false; | ||||
|  | ||||
|             self.request.requestFailed(@errorName(err)); | ||||
|             self.request.deinit(); | ||||
|         } | ||||
|  | ||||
|   | ||||
| @@ -59,6 +59,7 @@ pub const Notification = struct { | ||||
|         page_created: List = .{}, | ||||
|         page_navigate: List = .{}, | ||||
|         page_navigated: List = .{}, | ||||
|         http_request_fail: List = .{}, | ||||
|         http_request_start: List = .{}, | ||||
|         http_request_complete: List = .{}, | ||||
|         notification_created: List = .{}, | ||||
| @@ -69,6 +70,7 @@ pub const Notification = struct { | ||||
|         page_created: *page.Page, | ||||
|         page_navigate: *const PageNavigate, | ||||
|         page_navigated: *const PageNavigated, | ||||
|         http_request_fail: *const RequestFail, | ||||
|         http_request_start: *const RequestStart, | ||||
|         http_request_complete: *const RequestComplete, | ||||
|         notification_created: *Notification, | ||||
| @@ -97,6 +99,12 @@ pub const Notification = struct { | ||||
|         has_body: bool, | ||||
|     }; | ||||
|  | ||||
|     pub const RequestFail = struct { | ||||
|         id: usize, | ||||
|         url: *const std.Uri, | ||||
|         err: []const u8, | ||||
|     }; | ||||
|  | ||||
|     pub const RequestComplete = struct { | ||||
|         id: usize, | ||||
|         url: *const std.Uri, | ||||
|   | ||||
| @@ -127,7 +127,6 @@ pub const Loop = struct { | ||||
|         } | ||||
|     } | ||||
|  | ||||
|  | ||||
|     // JS callbacks APIs | ||||
|     // ----------------- | ||||
|  | ||||
| @@ -255,7 +254,6 @@ pub const Loop = struct { | ||||
|             } | ||||
|         }.onConnect; | ||||
|  | ||||
|  | ||||
|         const callback = try self.event_callback_pool.create(); | ||||
|         errdefer self.event_callback_pool.destroy(callback); | ||||
|         callback.* = .{ .loop = self, .ctx = ctx }; | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Karl Seguin
					Karl Seguin