mirror of
https://github.com/lightpanda-io/browser.git
synced 2026-06-11 01:25:53 -04:00
Ensure about:blank frame visibility
Our navigate on about:blank short-circuits most of the complex logic and loads
the content then and there, not asynchronously. This results in notifications
for the frame navigation/creation that happen immediately. With the current
code ordering though, the frame isn't entered in child_frames until AFTER
navigation, resulting in these events trigger on a frame which can't be found
via Session.findFrameByFrameId
This code adds the frame to child_frames BEFORE navigate (and removes it on
error).
Note: about:blank iframe navigation is more common than you probably think. As
soon as a frame is [dynamically] created, it navigates to about:blank, e.g.:
let iframe = document.createElement('iframe');
// IMPLICIT navigation to about:blank happens here
// and this will be another navigation event
iframe.src = "keemun.php";
This commit is contained in:
@@ -1379,6 +1379,11 @@ pub fn iframeAddedCallback(self: *Frame, iframe: *IFrame) !void {
|
||||
);
|
||||
};
|
||||
|
||||
// Append the new frame before navigate() so synchronous navigation paths
|
||||
// (about:blank, blob:) and the notifications they dispatch can see this
|
||||
// frame in self.child_frames.
|
||||
try self.child_frames.append(self.arena, new_frame);
|
||||
|
||||
// Iframe's initial src request carries the parent's URL as Referer and
|
||||
// as the SameSite initiator. Parent frame outlives this navigate()
|
||||
// call, so the slice is safe.
|
||||
@@ -1388,20 +1393,22 @@ pub fn iframeAddedCallback(self: *Frame, iframe: *IFrame) !void {
|
||||
.referer = parent_url,
|
||||
.initiator_url = parent_url,
|
||||
}) catch |err| {
|
||||
// extra defensive..maybe navigate added a new fame, and the index it
|
||||
// was added at was removed. Or maybe this frame was removed somehow
|
||||
// (which I don't think is possible)
|
||||
if (std.mem.indexOfScalar(*Frame, self.child_frames.items, new_frame)) |idx| {
|
||||
_ = self.child_frames.swapRemove(idx);
|
||||
}
|
||||
log.warn(.frame, "iframe navigate failure", .{ .url = url, .err = err });
|
||||
self._pending_loads -= 1;
|
||||
iframe._window = null;
|
||||
return error.IFrameLoadError;
|
||||
};
|
||||
|
||||
// window[N] is based on document order. For now we'll just append the frame
|
||||
// at the end of our list and set child_frames_sorted == false. window.getFrame
|
||||
// will check this flag to decide if it needs to sort the frames or not.
|
||||
// But, we can optimize this a bit. Since we expect frames to often be
|
||||
// added in document order, we can do a quick check to see whether the list
|
||||
// is sorted or not.
|
||||
try self.child_frames.append(self.arena, new_frame);
|
||||
|
||||
// window[N] is based on document order. We appended above and rely on
|
||||
// child_frames_sorted to tell window.getFrame whether it has to sort.
|
||||
// Since we expect frames to often be added in document order, do a quick
|
||||
// check to keep the list flagged as sorted when possible.
|
||||
const frames_len = self.child_frames.items.len;
|
||||
if (frames_len == 1) {
|
||||
// this is the only frame, it must be sorted.
|
||||
|
||||
Reference in New Issue
Block a user