mirror of
https://github.com/lightpanda-io/browser.git
synced 2026-09-15 07:19:20 -04:00
HttpClient: check the adblocker inside isUrlBlocked`
This commit is contained in:
2 files changed
+29
-27
No files matched your search
+29
-25
@@ -35,7 +35,6 @@ const Network = @import("Network.zig");
|
||||
const Cache = @import("cache/Cache.zig");
|
||||
const RobotsGate = @import("RobotsGate.zig");
|
||||
const UrlBlocklist = @import("UrlBlocklist.zig");
|
||||
const AdBlocker = @import("adblock/AdBlocker.zig");
|
||||
|
||||
pub const BlockPattern = UrlBlocklist.Pattern;
|
||||
|
||||
@@ -187,10 +186,6 @@ obey_robots: bool,
|
||||
|
||||
robots: RobotsGate,
|
||||
url_blocklist: ?UrlBlocklist,
|
||||
/// Hostname dictionaries built from `--adblock-lists`. Owned by Network,
|
||||
/// parsed once at startup and read-only from here on, so every client
|
||||
/// shares the one copy.
|
||||
adblocker: ?*const AdBlocker,
|
||||
|
||||
pub fn init(self: *Client, allocator: Allocator, network: *Network, cdp: ?*CDP) !void {
|
||||
var handles = try http.Handles.init(network.config);
|
||||
@@ -230,7 +225,6 @@ pub fn init(self: *Client, allocator: Allocator, network: *Network, cdp: ?*CDP)
|
||||
.obey_robots = network.config.obeyRobots(),
|
||||
.robots = .{ .allocator = allocator, .network = network },
|
||||
.url_blocklist = url_blocklist,
|
||||
.adblocker = if (network.adblocker) |*blocker| blocker else null,
|
||||
.arena_pool = &network.app.arena_pool,
|
||||
};
|
||||
}
|
||||
@@ -376,15 +370,19 @@ fn clearUrlBlocklist(self: *Client) void {
|
||||
}
|
||||
}
|
||||
|
||||
fn isUrlBlocked(self: *const Client, url: []const u8, internal: bool) bool {
|
||||
/// Every reason a request is refused before it reaches the network:
|
||||
/// `--block-urls` patterns and the `--adblock-lists` filters both land here
|
||||
/// so that no call site can apply one without the other.
|
||||
fn isUrlBlocked(self: *const Client, url: [:0]const u8, internal: bool) bool {
|
||||
if (internal) return false;
|
||||
const blocklist = self.url_blocklist orelse return false;
|
||||
return blocklist.isBlocked(url);
|
||||
if (self.url_blocklist) |*blocklist| {
|
||||
if (blocklist.isBlocked(url)) return true;
|
||||
}
|
||||
return self.isHostAdblocked(url);
|
||||
}
|
||||
|
||||
fn isHostAdblocked(self: *const Client, url: [:0]const u8, internal: bool) bool {
|
||||
if (internal) return false;
|
||||
const blocker = self.adblocker orelse return false;
|
||||
fn isHostAdblocked(self: *const Client, url: [:0]const u8) bool {
|
||||
const blocker = if (self.network.adblocker) |*b| b else return false;
|
||||
const host = URL.getHostname(url);
|
||||
if (host.len == 0 or host.len > 253) return false;
|
||||
// The trie expects normalized (lowercase) hostnames; URLs aren't
|
||||
@@ -862,13 +860,9 @@ fn pipeline(self: *Client, transfer: *Transfer, from: SubmitFrom) !void {
|
||||
},
|
||||
.after_intercept => {
|
||||
if (self.isUrlBlocked(transfer.req.url, transfer.req.internal)) {
|
||||
log.warn(.http, "blocked url", .{ .url = transfer.req.url });
|
||||
log.info(.http, "blocked url", .{ .url = transfer.req.url });
|
||||
return transfer.failAsync(error.UrlBlocked);
|
||||
}
|
||||
if (self.isHostAdblocked(transfer.req.url, transfer.req.internal)) {
|
||||
log.info(.http, "adblock blocked", .{ .url = transfer.req.url });
|
||||
return transfer.failAsync(error.AdblockBlocked);
|
||||
}
|
||||
if (try self.cacheLookup(transfer)) {
|
||||
// response came from the cache, we're done
|
||||
return;
|
||||
@@ -1508,7 +1502,7 @@ fn processOneMessage(self: *Client, msg: http.Handles.MultiMessage, transfer: *T
|
||||
}
|
||||
|
||||
if (self.isUrlBlocked(transfer.req.url, transfer.req.internal)) {
|
||||
log.warn(.http, "blocked url", .{ .url = transfer.req.url });
|
||||
log.info(.http, "blocked url", .{ .url = transfer.req.url });
|
||||
self.removeConn(msg.conn);
|
||||
transfer._conn = null;
|
||||
transfer.failAsync(error.UrlBlocked);
|
||||
@@ -3241,6 +3235,11 @@ const Synthetic = struct {
|
||||
};
|
||||
|
||||
const testing = @import("../testing.zig");
|
||||
const AdBlocker = @import("adblock/AdBlocker.zig");
|
||||
|
||||
// The Network every test client points at: only the fields a test actually
|
||||
// exercises are ever set, by initTestClient or by the test itself.
|
||||
var test_network: Network = undefined;
|
||||
|
||||
test "HttpClient: isFetchInterceptionMethod matches the four Fetch methods" {
|
||||
try testing.expect(isFetchInterceptionMethod("Fetch.continueRequest"));
|
||||
@@ -3411,7 +3410,10 @@ fn initTestClient(client: *Client, pool: *ArenaPool) void {
|
||||
client.obey_robots = false;
|
||||
client.robots = .{ .allocator = testing.allocator, .network = undefined };
|
||||
client.url_blocklist = null;
|
||||
client.adblocker = null;
|
||||
// isUrlBlocked reaches through here for the adblocker; tests that want
|
||||
// one assign it to `client.network` after this returns.
|
||||
test_network.adblocker = null;
|
||||
client.network = &test_network;
|
||||
}
|
||||
|
||||
test "HttpClient: setBlockedUrls owns, replaces, and clears patterns" {
|
||||
@@ -3449,15 +3451,16 @@ test "HttpClient: adblock verdicts apply per request hostname" {
|
||||
\\@@||good.ads.example.com^
|
||||
);
|
||||
try blocker.parse(&list);
|
||||
client.adblocker = &blocker;
|
||||
client.network.adblocker = blocker;
|
||||
defer client.network.adblocker = null;
|
||||
|
||||
try testing.expect(client.isHostAdblocked("https://ads.example.com/pixel.gif", false));
|
||||
try testing.expect(client.isUrlBlocked("https://ads.example.com/pixel.gif", false));
|
||||
// Hostnames are matched case-insensitively and without the port.
|
||||
try testing.expect(client.isHostAdblocked("https://SUB.ADS.EXAMPLE.COM:8443/x", false));
|
||||
try testing.expect(!client.isHostAdblocked("https://good.ads.example.com/app.js", false));
|
||||
try testing.expect(!client.isHostAdblocked("https://example.com/", false));
|
||||
try testing.expect(client.isUrlBlocked("https://SUB.ADS.EXAMPLE.COM:8443/x", false));
|
||||
try testing.expect(!client.isUrlBlocked("https://good.ads.example.com/app.js", false));
|
||||
try testing.expect(!client.isUrlBlocked("https://example.com/", false));
|
||||
// Internal transfers (robots.txt, ...) are never adblocked.
|
||||
try testing.expect(!client.isHostAdblocked("https://ads.example.com/", true));
|
||||
try testing.expect(!client.isUrlBlocked("https://ads.example.com/", true));
|
||||
}
|
||||
|
||||
test "HttpClient: URL blocking exempts internal transfers" {
|
||||
@@ -3696,6 +3699,7 @@ test "HttpClient: fulfillIntercepted follows a 3xx redirect" {
|
||||
// network.cache and the (empty) connection pool are read on this path.
|
||||
var net: Network = undefined;
|
||||
net.cache = null;
|
||||
net.adblocker = null;
|
||||
// An empty pool makes processTransfer queue the re-issued request
|
||||
// instead of putting it on the wire — the queue IS the capture.
|
||||
net.available = .{};
|
||||
|
||||
Reference in new issue
Block a user