diff --git a/src/browser/Page.zig b/src/browser/Page.zig index 4a586be8..df47ab60 100644 --- a/src/browser/Page.zig +++ b/src/browser/Page.zig @@ -438,7 +438,15 @@ pub fn releaseArena(self: *Page, allocator: Allocator) void { pub fn isSameOrigin(self: *const Page, url: [:0]const u8) !bool { const current_origin = self.origin orelse return false; - return std.mem.startsWith(u8, url, current_origin); + + // fastpath + if (!std.mem.startsWith(u8, url, current_origin)) { + return false; + } + + // Starting here, at least protocols are equals. + // Compare hosts (domain:port) strictly + return std.mem.eql(u8, URL.getHost(url), URL.getHost(current_origin)); } /// Look up a blob URL in this page's registry. @@ -3616,3 +3624,41 @@ test "WebApi: Frames" { test "WebApi: Integration" { try testing.htmlRunner("integration", .{}); } + +test "Page: isSameOrigin" { + var arena = std.heap.ArenaAllocator.init(testing.allocator); + defer arena.deinit(); + const allocator = arena.allocator(); + + var page: Page = undefined; + + page.origin = null; + try testing.expectEqual(false, page.isSameOrigin("https://origin.com/")); + + page.origin = try URL.getOrigin(allocator, "https://origin.com/foo/bar") orelse unreachable; + try testing.expectEqual(true, page.isSameOrigin("https://origin.com/foo/bar")); // exact same + try testing.expectEqual(true, page.isSameOrigin("https://origin.com/bar/bar")); // path differ + try testing.expectEqual(true, page.isSameOrigin("https://origin.com/")); // path differ + try testing.expectEqual(true, page.isSameOrigin("https://origin.com")); // no path + try testing.expectEqual(true, page.isSameOrigin("https://origin.com/foo?q=1")); + try testing.expectEqual(true, page.isSameOrigin("https://origin.com/foo#hash")); + try testing.expectEqual(true, page.isSameOrigin("https://origin.com/foo?q=1#hash")); + // FIXME try testing.expectEqual(true, page.isSameOrigin("https://foo:bar@origin.com")); + // FIXME try testing.expectEqual(true, page.isSameOrigin("https://origin.com:443/foo")); + + try testing.expectEqual(false, page.isSameOrigin("http://origin.com/")); // another proto + try testing.expectEqual(false, page.isSameOrigin("https://origin.com:123/")); // another port + try testing.expectEqual(false, page.isSameOrigin("https://sub.origin.com/")); // another subdomain + try testing.expectEqual(false, page.isSameOrigin("https://target.com/")); // different domain + try testing.expectEqual(false, page.isSameOrigin("https://origin.com.target.com/")); // different domain + try testing.expectEqual(false, page.isSameOrigin("https://target.com/@origin.com")); + + page.origin = try URL.getOrigin(allocator, "https://origin.com:8443/foo") orelse unreachable; + try testing.expectEqual(true, page.isSameOrigin("https://origin.com:8443/bar")); + try testing.expectEqual(false, page.isSameOrigin("https://origin.com/bar")); // missing port + try testing.expectEqual(false, page.isSameOrigin("https://origin.com:9999/bar")); // wrong port + + try testing.expectEqual(false, page.isSameOrigin("")); + try testing.expectEqual(false, page.isSameOrigin("not-a-url")); + try testing.expectEqual(false, page.isSameOrigin("//origin.com/foo")); +} diff --git a/src/browser/URL.zig b/src/browser/URL.zig index dd49bfb9..6f8cbebd 100644 --- a/src/browser/URL.zig +++ b/src/browser/URL.zig @@ -509,7 +509,7 @@ fn getUserInfo(raw: [:0]const u8) ?[]const u8 { return raw[authority_start .. auth.host_start - 1]; } -pub fn getHost(raw: [:0]const u8) []const u8 { +pub fn getHost(raw: []const u8) []const u8 { const auth = parseAuthority(raw) orelse return ""; return auth.getHost(raw); }