Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,9 @@ npm-debug.log
src/rule_resources
src/static_pages

# Downloaded binaries
scripts/bin/

# Build
dist/
web-ext-artifacts/
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
"version": "10.5.39",
"type": "module",
"scripts": {
"postinstall": "node scripts/download-validate-dnr-rules.js",
Comment thread
smalluban marked this conversation as resolved.
Outdated
"build": "node scripts/build.js",
"start": "npm run build -- --watch",
"start:update": "./scripts/update.sh",
Expand Down
54 changes: 54 additions & 0 deletions scripts/download-validate-dnr-rules.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
/**
* Ghostery Browser Extension
* https://www.ghostery.com/
*
* Copyright 2017-present Ghostery GmbH. All rights reserved.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0
*/

import { existsSync, mkdirSync, writeFileSync, chmodSync } from 'node:fs';
import { resolve } from 'node:path';

const PLATFORM_MAP = {
'darwin-arm64': 'macos-arm64',
'darwin-x64': 'macos-arm64',
'linux-x64': 'linux-x64',
};

const binDir = resolve(import.meta.dirname, 'bin');
const binPath = resolve(binDir, 'validate-dnr-rules');

const key = `${process.platform}-${process.arch}`;
const suffix = PLATFORM_MAP[key];

if (!suffix) {
console.log(`[validate-dnr-rules] Skipping download: no binary available for ${key}.`);
process.exit(0);
}

if (existsSync(binPath)) {
process.exit(0);
}

const url = `https://github.com/ghostery/WebKit/releases/latest/download/validate-dnr-rules-${suffix}`;

console.log(`[validate-dnr-rules] Downloading ${url}`);

try {
const res = await fetch(url);
if (!res.ok) {
throw new Error(`HTTP ${res.status} ${res.statusText}`);
}
mkdirSync(binDir, { recursive: true });
writeFileSync(binPath, new Uint8Array(await res.arrayBuffer()));
chmodSync(binPath, 0o755);
console.log(`[validate-dnr-rules] Saved to ${binPath}`);
} catch (err) {
console.warn(
`[validate-dnr-rules] Download failed: ${err.message}. Safari builds will not filter invalid DNR rules until this succeeds.`,
);
process.exit(0);
}
81 changes: 81 additions & 0 deletions scripts/filter-invalid-dnr-rules.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
/**
* Ghostery Browser Extension
* https://www.ghostery.com/
*
* Copyright 2017-present Ghostery GmbH. All rights reserved.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0
*/

import { existsSync, readdirSync, readFileSync, writeFileSync } from 'node:fs';
import { join, relative, resolve } from 'node:path';
import { spawnSync } from 'node:child_process';

const binPath = resolve(import.meta.dirname, 'bin', 'validate-dnr-rules');
const rulesDir = resolve(process.cwd(), 'dist', 'rule_resources');

if (!existsSync(binPath)) {
console.error(
`[filter-invalid-dnr-rules] Validator binary not found at ${binPath}.\n` +
`Run 'npm install' to download it from https://github.com/ghostery/WebKit/releases.`,
);
process.exit(1);
}

if (!existsSync(rulesDir)) {
console.error(`[filter-invalid-dnr-rules] Rules directory not found: ${rulesDir}`);
process.exit(1);
}

const files = readdirSync(rulesDir)
.filter((f) => f.startsWith('dnr-') && f.endsWith('.json') && !f.endsWith('.metadata.json'))
.map((f) => join(rulesDir, f));

const ERROR_RE = /^\s*ERROR: Rule (-?\d+)/gm;

let totalRemoved = 0;

for (const file of files) {
const result = spawnSync(binPath, [file], {
encoding: 'utf8',
maxBuffer: 256 * 1024 * 1024,
});

if (result.error) {
console.error(`[filter-invalid-dnr-rules] Failed to spawn validator: ${result.error.message}`);
process.exit(1);
}

if (result.status === 0) {
continue;
}

const invalidIds = new Set();
for (const m of result.stdout.matchAll(ERROR_RE)) {
invalidIds.add(Number(m[1]));
}

if (invalidIds.size === 0) {
console.error(
`[filter-invalid-dnr-rules] Validator failed for ${file} but produced no parseable errors:\n${result.stdout}${result.stderr}`,
);
process.exit(1);
}

const rules = JSON.parse(readFileSync(file, 'utf8'));
const filtered = rules.filter((r) => !invalidIds.has(r.id));
const removed = rules.length - filtered.length;

writeFileSync(file, JSON.stringify(filtered));
totalRemoved += removed;

console.log(
`[filter-invalid-dnr-rules] ${relative(process.cwd(), file)}: removed ${removed}/${rules.length} invalid rule(s)`,
);
}

console.log(
`[filter-invalid-dnr-rules] Removed ${totalRemoved} rule(s) across ${files.length} ruleset(s).`,
);
3 changes: 3 additions & 0 deletions xcode/ci_scripts/build.sh
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@ test -f /usr/local/opt/asdf/libexec/asdf.sh && . /usr/local/opt/asdf/libexec/asd
# run build script
npm run build -- --clean

# strip DNR rules that WebKit's URL filter parser cannot compile
node scripts/filter-invalid-dnr-rules.js

# rewrite manifest background.service_worker into background.scripts/persistent
node -e '
const fs = require("fs");
Expand Down