forked from icd/rentgen
Compare commits
No commits in common. "develop" and "develop" have entirely different histories.
@ -1,16 +0,0 @@
|
|||||||
.log
|
|
||||||
node_modules
|
|
||||||
sidebar.js
|
|
||||||
web-ext-artifacts/
|
|
||||||
lib/*
|
|
||||||
yarn-error.log
|
|
||||||
rentgen.zip
|
|
||||||
|
|
||||||
# Generated PNG icons (build artifacts)
|
|
||||||
assets/icons/*.png
|
|
||||||
assets/icon-addon-*.png
|
|
||||||
|
|
||||||
# Exception: do not ignore the `browser-api` directory inside `lib`
|
|
||||||
!/lib/browser-api/
|
|
||||||
|
|
||||||
Dockerfile
|
|
||||||
3
.gitignore
vendored
3
.gitignore
vendored
@ -2,7 +2,6 @@
|
|||||||
node_modules
|
node_modules
|
||||||
sidebar.js
|
sidebar.js
|
||||||
/web-ext-artifacts/
|
/web-ext-artifacts/
|
||||||
/artifacts/
|
|
||||||
lib/*
|
lib/*
|
||||||
/yarn-error.log
|
/yarn-error.log
|
||||||
/rentgen.zip
|
/rentgen.zip
|
||||||
@ -13,5 +12,3 @@ lib/*
|
|||||||
|
|
||||||
# Exception: do not ignore the `browser-api` directory inside `lib`
|
# Exception: do not ignore the `browser-api` directory inside `lib`
|
||||||
!/lib/browser-api/
|
!/lib/browser-api/
|
||||||
|
|
||||||
.claude
|
|
||||||
|
|||||||
112
Dockerfile
112
Dockerfile
@ -1,112 +0,0 @@
|
|||||||
# Rentgen Browser Extension - Docker Build
|
|
||||||
# See README.md for detailed usage instructions
|
|
||||||
|
|
||||||
# Build stage
|
|
||||||
FROM node:lts AS builder
|
|
||||||
|
|
||||||
WORKDIR /app
|
|
||||||
|
|
||||||
# Copy package files for dependency installation (better layer caching)
|
|
||||||
COPY package.json package-lock.json ./
|
|
||||||
|
|
||||||
# Install dependencies
|
|
||||||
RUN npm install
|
|
||||||
|
|
||||||
# FIXME: COPY . . invalidates cache, so we need to optionally install Firefox
|
|
||||||
# and jump back to the correct stage. It might be too complex though, so we
|
|
||||||
# either need to use build args (if cache properly) or heavily document the
|
|
||||||
# stage transitions, maybe even with a graph.
|
|
||||||
|
|
||||||
# Copy source code (respecting .dockerignore)
|
|
||||||
COPY . .
|
|
||||||
|
|
||||||
# Build the extension for Firefox (default) - without tests
|
|
||||||
RUN npm run build
|
|
||||||
|
|
||||||
# Create the package
|
|
||||||
RUN npm run create-package
|
|
||||||
|
|
||||||
# Test builder stage - builds with ENABLE_TESTS=true
|
|
||||||
FROM node:lts AS test_builder
|
|
||||||
|
|
||||||
WORKDIR /app
|
|
||||||
|
|
||||||
# Copy package files for dependency installation
|
|
||||||
COPY package.json package-lock.json ./
|
|
||||||
|
|
||||||
# Install dependencies
|
|
||||||
RUN npm install
|
|
||||||
|
|
||||||
# Copy source code
|
|
||||||
COPY . .
|
|
||||||
|
|
||||||
# Build with tests enabled
|
|
||||||
RUN ENABLE_TESTS=true npm run build
|
|
||||||
|
|
||||||
# Create the package
|
|
||||||
RUN npm run create-package
|
|
||||||
|
|
||||||
# Code quality stage - for running quality checks
|
|
||||||
FROM builder AS code_quality
|
|
||||||
COPY tests/run-checks.sh /app/tests/run-checks.sh
|
|
||||||
RUN chmod +x /app/tests/run-checks.sh && /app/tests/run-checks.sh
|
|
||||||
|
|
||||||
# Artifacts stage - only contains the built artifacts (for --output)
|
|
||||||
FROM scratch AS artifacts
|
|
||||||
|
|
||||||
# Copy only the built extension zip file to root
|
|
||||||
COPY --from=builder /app/web-ext-artifacts/*.zip /
|
|
||||||
|
|
||||||
# Default stage - full development environment
|
|
||||||
FROM builder
|
|
||||||
|
|
||||||
# Default command shows the built artifact
|
|
||||||
CMD ["ls", "-lh", "/app/web-ext-artifacts/"]
|
|
||||||
|
|
||||||
# Runtime stage - for running extension in Firefox
|
|
||||||
FROM node:lts AS runtime
|
|
||||||
|
|
||||||
WORKDIR /app
|
|
||||||
|
|
||||||
# Copy built extension from test_builder (includes test code)
|
|
||||||
COPY --from=test_builder /app /app
|
|
||||||
|
|
||||||
# Install Firefox and Xvfb for headless execution (cached layer)
|
|
||||||
RUN apt-get update && apt-get install -y \
|
|
||||||
firefox-esr \
|
|
||||||
xvfb \
|
|
||||||
procps \
|
|
||||||
&& rm -rf /var/lib/apt/lists/*
|
|
||||||
|
|
||||||
# Install Python and pip in a separate layer for better caching
|
|
||||||
RUN apt-get update && apt-get install -y \
|
|
||||||
python3-pip \
|
|
||||||
wget \
|
|
||||||
&& rm -rf /var/lib/apt/lists/*
|
|
||||||
|
|
||||||
# Install geckodriver for WebDriver protocol
|
|
||||||
RUN wget -q https://github.com/mozilla/geckodriver/releases/download/v0.34.0/geckodriver-v0.34.0-linux64.tar.gz \
|
|
||||||
&& tar -xzf geckodriver-v0.34.0-linux64.tar.gz \
|
|
||||||
&& mv geckodriver /usr/local/bin/ \
|
|
||||||
&& rm geckodriver-v0.34.0-linux64.tar.gz \
|
|
||||||
&& chmod +x /usr/local/bin/geckodriver
|
|
||||||
|
|
||||||
# Install Python dependencies for testing
|
|
||||||
RUN pip3 install --break-system-packages marionette_driver
|
|
||||||
|
|
||||||
# Set display for Xvfb
|
|
||||||
ENV DISPLAY=:99
|
|
||||||
|
|
||||||
# Start script (not used in verify stage)
|
|
||||||
CMD ["echo", "Use verify stage for testing"]
|
|
||||||
|
|
||||||
# Integration test stage - automated testing with exit code
|
|
||||||
FROM runtime AS integration_test
|
|
||||||
|
|
||||||
# Copy verification scripts
|
|
||||||
COPY tests/test_verify.py /app/tests/test_verify.py
|
|
||||||
COPY tests/test-lib.js /app/tests/test-lib.js
|
|
||||||
RUN chmod +x /app/tests/test_verify.py
|
|
||||||
|
|
||||||
# Run verification and exit with proper exit code
|
|
||||||
CMD ["python3", "/app/tests/test_verify.py"]
|
|
||||||
29
README.md
29
README.md
@ -21,21 +21,9 @@ Firefox: https://addons.mozilla.org/en-US/firefox/addon/rentgen/
|
|||||||
### Pre-requirements
|
### Pre-requirements
|
||||||
|
|
||||||
- OS: Linux x86_64
|
- OS: Linux x86_64
|
||||||
- Node.js: 25.x version (recommended: use [fnm](https://github.com/Schniz/fnm) for automatic version management)
|
- Node.js: 16.x version
|
||||||
- npm: 7.x version or higher
|
- npm: 7.x version or higher
|
||||||
|
|
||||||
**Using fnm (recommended):**
|
|
||||||
|
|
||||||
If you're using fnm, it will automatically use the correct Node.js version specified in `.nvmrc`:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Install fnm (if not already installed)
|
|
||||||
curl -fsSL https://fnm.vercel.app/install | bash
|
|
||||||
|
|
||||||
# In the project directory, fnm will automatically use Node.js 25
|
|
||||||
fnm use
|
|
||||||
```
|
|
||||||
|
|
||||||
### Build steps
|
### Build steps
|
||||||
|
|
||||||
1. Pull repository or download a zip package
|
1. Pull repository or download a zip package
|
||||||
@ -94,21 +82,9 @@ Firefox: https://addons.mozilla.org/pl/firefox/addon/rentgen/
|
|||||||
### Wymagania wstępne
|
### Wymagania wstępne
|
||||||
|
|
||||||
- System operacyjny: Linux x86_64
|
- System operacyjny: Linux x86_64
|
||||||
- Node.js: 25.x (zalecane: użyj [fnm](https://github.com/Schniz/fnm) do automatycznego zarządzania wersją)
|
- Node.js: 16.x
|
||||||
- npm: 7.x lub wyższy
|
- npm: 7.x lub wyższy
|
||||||
|
|
||||||
**Używanie fnm (zalecane):**
|
|
||||||
|
|
||||||
Jeśli używasz fnm, automatycznie użyje prawidłowej wersji Node.js określonej w `.nvmrc`:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Zainstaluj fnm (jeśli nie jest zainstalowane)
|
|
||||||
curl -fsSL https://fnm.vercel.app/install | bash
|
|
||||||
|
|
||||||
# W katalogu projektu fnm automatycznie użyje Node.js 25
|
|
||||||
fnm use
|
|
||||||
```
|
|
||||||
|
|
||||||
### Proces budowy
|
### Proces budowy
|
||||||
|
|
||||||
1. Pobierz repozytorium przez `git pull https://git.internet-czas-dzialac.pl/icd/rentgen.git` lub pobierz archwium zip
|
1. Pobierz repozytorium przez `git pull https://git.internet-czas-dzialac.pl/icd/rentgen.git` lub pobierz archwium zip
|
||||||
@ -136,4 +112,3 @@ Każdy problem zostanie sprawdzony i przeniesiony na wewnętrzną listę problem
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
# Test pre-commit hook - without Docker check
|
|
||||||
|
|||||||
@ -1,35 +1,3 @@
|
|||||||
import { init, getMemory } from "./memory";
|
import { init } from "./memory";
|
||||||
|
|
||||||
// Use global browser object directly (available in extension context)
|
|
||||||
declare const browser: any;
|
|
||||||
declare const ENABLE_TESTS: boolean;
|
|
||||||
|
|
||||||
init();
|
init();
|
||||||
|
|
||||||
// Test verification handler for Marionette tests
|
|
||||||
// Tests real Rentgen functionality: counting third-party domains
|
|
||||||
if (ENABLE_TESTS) {
|
|
||||||
browser.runtime.onMessage.addListener((message: any, sender: any, sendResponse: any) => {
|
|
||||||
if (message.type === 'RENTGEN_TEST_VERIFICATION') {
|
|
||||||
// Get the origin from message (sent by content script)
|
|
||||||
const origin = message.origin;
|
|
||||||
|
|
||||||
// Access the memory to get clusters for this origin
|
|
||||||
const memory = getMemory();
|
|
||||||
const clusters = memory.getClustersForOrigin(origin);
|
|
||||||
const badgeCount = Object.keys(clusters).length;
|
|
||||||
|
|
||||||
// Send back the badge count (number of third-party domains)
|
|
||||||
const response = {
|
|
||||||
success: true,
|
|
||||||
badgeCount: badgeCount,
|
|
||||||
origin: origin,
|
|
||||||
clusterIds: Object.keys(clusters),
|
|
||||||
backgroundTimestamp: Date.now()
|
|
||||||
};
|
|
||||||
|
|
||||||
sendResponse(response);
|
|
||||||
return true; // Keep channel open for async response
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|||||||
@ -8,7 +8,7 @@ import verbs, { v } from './verbs';
|
|||||||
export default function useSurvey(
|
export default function useSurvey(
|
||||||
clusters: RequestCluster[],
|
clusters: RequestCluster[],
|
||||||
{ onComplete }: { onComplete: (sender: { data: RawAnswers }) => void }
|
{ onComplete }: { onComplete: (sender: { data: RawAnswers }) => void }
|
||||||
): Survey.Model | null {
|
): Survey.ReactSurveyModel | null {
|
||||||
const [survey, setSurvey] = React.useState<Survey.Model | null>(null);
|
const [survey, setSurvey] = React.useState<Survey.Model | null>(null);
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
const model = generateSurveyQuestions(clusters);
|
const model = generateSurveyQuestions(clusters);
|
||||||
|
|||||||
@ -43,6 +43,7 @@ export function StolenData({
|
|||||||
origin={origin}
|
origin={origin}
|
||||||
shorthost={cluster.id}
|
shorthost={cluster.id}
|
||||||
key={cluster.id + origin}
|
key={cluster.id + origin}
|
||||||
|
refreshToken={eventCounts[cluster.id] || 0}
|
||||||
minValueLength={minValueLength}
|
minValueLength={minValueLength}
|
||||||
cookiesOnly={cookiesOnly}
|
cookiesOnly={cookiesOnly}
|
||||||
cookiesOrOriginOnly={cookiesOrOriginOnly}
|
cookiesOrOriginOnly={cookiesOrOriginOnly}
|
||||||
|
|||||||
21
compose.yml
21
compose.yml
@ -1,21 +0,0 @@
|
|||||||
services:
|
|
||||||
rentgen_build:
|
|
||||||
build: .
|
|
||||||
|
|
||||||
rentgen_check:
|
|
||||||
build:
|
|
||||||
context: .
|
|
||||||
target: code_quality
|
|
||||||
|
|
||||||
rentgen_run:
|
|
||||||
build:
|
|
||||||
context: .
|
|
||||||
target: runtime
|
|
||||||
stdin_open: true
|
|
||||||
tty: true
|
|
||||||
|
|
||||||
rentgen_verify:
|
|
||||||
build:
|
|
||||||
context: .
|
|
||||||
target: integration_test
|
|
||||||
restart: "no"
|
|
||||||
@ -1,7 +1,5 @@
|
|||||||
import esbuild from 'esbuild';
|
import esbuild from 'esbuild';
|
||||||
import scss from 'esbuild-plugin-sass';
|
import scss from 'esbuild-plugin-sass';
|
||||||
import fs from 'fs';
|
|
||||||
import path from 'path';
|
|
||||||
|
|
||||||
const watch = process.argv.includes('--watch') && {
|
const watch = process.argv.includes('--watch') && {
|
||||||
onRebuild(error) {
|
onRebuild(error) {
|
||||||
@ -10,8 +8,6 @@ const watch = process.argv.includes('--watch') && {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
const ENABLE_TESTS = process.env.ENABLE_TESTS === 'true';
|
|
||||||
|
|
||||||
// see https://github.com/evanw/esbuild/issues/806#issuecomment-779138268
|
// see https://github.com/evanw/esbuild/issues/806#issuecomment-779138268
|
||||||
let skipReactImports = {
|
let skipReactImports = {
|
||||||
name: 'skipReactImports',
|
name: 'skipReactImports',
|
||||||
@ -45,7 +41,9 @@ let skipReactImports = {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
const entryPoints = [
|
esbuild
|
||||||
|
.build({
|
||||||
|
entryPoints: [
|
||||||
'components/toolbar/toolbar.tsx',
|
'components/toolbar/toolbar.tsx',
|
||||||
'components/sidebar/sidebar.tsx',
|
'components/sidebar/sidebar.tsx',
|
||||||
'components/report-window/report-window.tsx',
|
'components/report-window/report-window.tsx',
|
||||||
@ -53,15 +51,7 @@ const entryPoints = [
|
|||||||
'diag.tsx',
|
'diag.tsx',
|
||||||
'styles/global.scss',
|
'styles/global.scss',
|
||||||
'styles/fonts.scss',
|
'styles/fonts.scss',
|
||||||
];
|
],
|
||||||
|
|
||||||
if (ENABLE_TESTS) {
|
|
||||||
entryPoints.push('tests/test-content-script.js');
|
|
||||||
}
|
|
||||||
|
|
||||||
esbuild
|
|
||||||
.build({
|
|
||||||
entryPoints,
|
|
||||||
bundle: true,
|
bundle: true,
|
||||||
// minify: true,
|
// minify: true,
|
||||||
outdir: './lib',
|
outdir: './lib',
|
||||||
@ -70,39 +60,9 @@ esbuild
|
|||||||
define: {
|
define: {
|
||||||
PLUGIN_NAME: '"Rentgen"',
|
PLUGIN_NAME: '"Rentgen"',
|
||||||
PLUGIN_URL: '"https://addons.mozilla.org/pl/firefox/addon/rentgen/"',
|
PLUGIN_URL: '"https://addons.mozilla.org/pl/firefox/addon/rentgen/"',
|
||||||
ENABLE_TESTS: String(ENABLE_TESTS),
|
|
||||||
},
|
},
|
||||||
external: ['react', 'react-dom', 'survey-react'],
|
external: ['react', 'react-dom', 'survey-react'],
|
||||||
watch,
|
watch,
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => console.log('Add-on was built'))
|
||||||
console.log('Add-on was built');
|
|
||||||
|
|
||||||
// Modify manifest.json to include test content script when ENABLE_TESTS=true
|
|
||||||
if (ENABLE_TESTS) {
|
|
||||||
const manifestPath = path.join(process.cwd(), 'manifest.json');
|
|
||||||
const manifest = JSON.parse(fs.readFileSync(manifestPath, 'utf-8'));
|
|
||||||
|
|
||||||
// Add content_scripts for testing
|
|
||||||
if (!manifest.content_scripts) {
|
|
||||||
manifest.content_scripts = [];
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check if test script is already added
|
|
||||||
const hasTestScript = manifest.content_scripts.some(
|
|
||||||
cs => cs.js && cs.js.includes('lib/tests/test-content-script.js')
|
|
||||||
);
|
|
||||||
|
|
||||||
if (!hasTestScript) {
|
|
||||||
manifest.content_scripts.push({
|
|
||||||
matches: ['<all_urls>'],
|
|
||||||
js: ['lib/tests/test-content-script.js'],
|
|
||||||
run_at: 'document_start'
|
|
||||||
});
|
|
||||||
|
|
||||||
fs.writeFileSync(manifestPath, JSON.stringify(manifest, null, 4));
|
|
||||||
console.log('Added test content script to manifest.json');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.catch(() => process.exit(1));
|
.catch(() => process.exit(1));
|
||||||
|
|||||||
@ -13,7 +13,6 @@ function setDomainsCount(counter: number, tabId: number) {
|
|||||||
|
|
||||||
export default class Memory extends SaferEmitter {
|
export default class Memory extends SaferEmitter {
|
||||||
origin_to_history = {} as Record<string, Record<string, RequestCluster>>;
|
origin_to_history = {} as Record<string, Record<string, RequestCluster>>;
|
||||||
|
|
||||||
async register(request: ExtendedRequest) {
|
async register(request: ExtendedRequest) {
|
||||||
await request.init();
|
await request.init();
|
||||||
if (!request.isThirdParty()) {
|
if (!request.isThirdParty()) {
|
||||||
@ -46,6 +45,7 @@ export default class Memory extends SaferEmitter {
|
|||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
super();
|
super();
|
||||||
|
|
||||||
browser.webRequest.onBeforeRequest.addListener(
|
browser.webRequest.onBeforeRequest.addListener(
|
||||||
async (request) => {
|
async (request) => {
|
||||||
new ExtendedRequest(request);
|
new ExtendedRequest(request);
|
||||||
|
|||||||
@ -28,9 +28,6 @@
|
|||||||
"homepage": "https://git.internet-czas-dzialac.pl/icd/rentgen",
|
"homepage": "https://git.internet-czas-dzialac.pl/icd/rentgen",
|
||||||
"author": "Kuba Orlik, Arkadiusz Wieczorek",
|
"author": "Kuba Orlik, Arkadiusz Wieczorek",
|
||||||
"license": "GPL-3.0-or-later",
|
"license": "GPL-3.0-or-later",
|
||||||
"engines": {
|
|
||||||
"node": ">=25"
|
|
||||||
},
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@iabtcf/core": "^1.3.1",
|
"@iabtcf/core": "^1.3.1",
|
||||||
"@types/proposal-relative-indexing-method": "^0.1.0",
|
"@types/proposal-relative-indexing-method": "^0.1.0",
|
||||||
|
|||||||
@ -1,21 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
# Pre-commit hook for Rentgen extension
|
|
||||||
# Builds and runs verification tests before allowing commit
|
|
||||||
|
|
||||||
set -e
|
|
||||||
|
|
||||||
echo "Running pre-commit checks..."
|
|
||||||
|
|
||||||
# Build all stages
|
|
||||||
echo "Building Docker images..."
|
|
||||||
docker compose build
|
|
||||||
|
|
||||||
# Run code quality checks (typecheck + lint)
|
|
||||||
echo "Running code quality checks..."
|
|
||||||
docker compose up --abort-on-container-exit --exit-code-from rentgen_check rentgen_check
|
|
||||||
|
|
||||||
# Run integration tests
|
|
||||||
echo "Running integration tests..."
|
|
||||||
docker compose up --abort-on-container-exit --exit-code-from rentgen_verify rentgen_verify
|
|
||||||
|
|
||||||
echo "✓ All pre-commit checks passed!"
|
|
||||||
@ -1,13 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
# Code quality checks for Rentgen extension
|
|
||||||
# Runs typecheck and lint
|
|
||||||
|
|
||||||
set -e
|
|
||||||
|
|
||||||
echo "Running type checking..."
|
|
||||||
npm run typecheck
|
|
||||||
|
|
||||||
echo "Running linter..."
|
|
||||||
npm run lint
|
|
||||||
|
|
||||||
echo "✓ All code quality checks passed!"
|
|
||||||
@ -1,70 +0,0 @@
|
|||||||
// Test content script - only for automated testing
|
|
||||||
// This script proves bidirectional communication between content script and background
|
|
||||||
|
|
||||||
// Set initial DOM marker to prove content script is injected
|
|
||||||
|
|
||||||
(function() {
|
|
||||||
function setMarker() {
|
|
||||||
if (document.body) {
|
|
||||||
document.body.setAttribute('data-rentgen-injected', 'true');
|
|
||||||
} else {
|
|
||||||
// Wait for DOM ready
|
|
||||||
if (document.readyState === 'loading') {
|
|
||||||
document.addEventListener('DOMContentLoaded', () => {
|
|
||||||
document.body.setAttribute('data-rentgen-injected', 'true');
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
setMarker();
|
|
||||||
})();
|
|
||||||
|
|
||||||
// Listen for test request from Marionette test script
|
|
||||||
document.addEventListener('rentgen_test_request', async (event) => {
|
|
||||||
try {
|
|
||||||
// Mark that we received the event
|
|
||||||
document.body.setAttribute('data-rentgen-event-received', 'true');
|
|
||||||
|
|
||||||
// Extract test data from event
|
|
||||||
const testData = event.detail || {};
|
|
||||||
const timestamp = testData.timestamp || Date.now();
|
|
||||||
|
|
||||||
// Send message to background script to get badge count for this origin
|
|
||||||
// This tests real Rentgen functionality: counting third-party domains
|
|
||||||
const response = await browser.runtime.sendMessage({
|
|
||||||
type: 'RENTGEN_TEST_VERIFICATION',
|
|
||||||
origin: window.location.origin,
|
|
||||||
url: window.location.href,
|
|
||||||
title: document.title,
|
|
||||||
timestamp: timestamp
|
|
||||||
});
|
|
||||||
|
|
||||||
// Store the response from background in DOM
|
|
||||||
// This provides the badge count (number of third-party domains)
|
|
||||||
if (response && response.success) {
|
|
||||||
document.body.setAttribute('data-rentgen-verified', 'true');
|
|
||||||
document.body.setAttribute('data-rentgen-badge-count', String(response.badgeCount));
|
|
||||||
document.body.setAttribute('data-rentgen-origin', response.origin);
|
|
||||||
document.body.setAttribute('data-rentgen-cluster-ids', JSON.stringify(response.clusterIds));
|
|
||||||
document.body.setAttribute('data-rentgen-background-timestamp', String(response.backgroundTimestamp));
|
|
||||||
|
|
||||||
// Also dispatch a custom event with the results
|
|
||||||
document.dispatchEvent(new CustomEvent('rentgen_test_complete', {
|
|
||||||
detail: {
|
|
||||||
success: true,
|
|
||||||
badgeCount: response.badgeCount,
|
|
||||||
origin: response.origin,
|
|
||||||
clusterIds: response.clusterIds,
|
|
||||||
backgroundTimestamp: response.backgroundTimestamp
|
|
||||||
}
|
|
||||||
}));
|
|
||||||
} else {
|
|
||||||
document.body.setAttribute('data-rentgen-verified', 'false');
|
|
||||||
document.body.setAttribute('data-rentgen-error', 'No response from background');
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
// Store error in DOM for debugging
|
|
||||||
document.body.setAttribute('data-rentgen-verified', 'false');
|
|
||||||
document.body.setAttribute('data-rentgen-error', String(error));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
@ -1,55 +0,0 @@
|
|||||||
// Test library for Marionette-based extension verification
|
|
||||||
// This JavaScript code runs in the browser context via Marionette
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Check if test content script is loaded
|
|
||||||
* The content script is automatically injected by manifest.json when ENABLE_TESTS=true
|
|
||||||
* @returns {Promise<boolean>} - True if content script is loaded
|
|
||||||
*/
|
|
||||||
async function waitForTestContentScript() {
|
|
||||||
// Wait for content script to set the marker
|
|
||||||
let attempts = 0;
|
|
||||||
while (attempts < 50) {
|
|
||||||
if (document.body && document.body.getAttribute('data-rentgen-injected') === 'true') {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
await new Promise(resolve => setTimeout(resolve, 100));
|
|
||||||
attempts++;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Test that background script returns badge count correctly
|
|
||||||
* Tests real Rentgen functionality: counting third-party domains
|
|
||||||
* @returns {Promise<number|null>} - Badge count (number of third-party domains) or null on failure
|
|
||||||
*/
|
|
||||||
async function testBadgeCount() {
|
|
||||||
// Wait for content script to be loaded
|
|
||||||
const loaded = await waitForTestContentScript();
|
|
||||||
if (!loaded) {
|
|
||||||
return -1; // Content script not loaded
|
|
||||||
}
|
|
||||||
|
|
||||||
// Dispatch test request to content script
|
|
||||||
document.dispatchEvent(new CustomEvent('rentgen_test_request', {
|
|
||||||
detail: { timestamp: Date.now() }
|
|
||||||
}));
|
|
||||||
|
|
||||||
// Wait for background response with badge count
|
|
||||||
return new Promise((resolve) => {
|
|
||||||
let attempts = 0;
|
|
||||||
const checkInterval = setInterval(() => {
|
|
||||||
attempts++;
|
|
||||||
const badgeCount = document.body.getAttribute('data-rentgen-badge-count');
|
|
||||||
|
|
||||||
if (badgeCount !== null) {
|
|
||||||
clearInterval(checkInterval);
|
|
||||||
resolve(parseInt(badgeCount));
|
|
||||||
} else if (attempts > 50) {
|
|
||||||
clearInterval(checkInterval);
|
|
||||||
resolve(null);
|
|
||||||
}
|
|
||||||
}, 100);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
@ -1,155 +0,0 @@
|
|||||||
#!/usr/bin/env python3
|
|
||||||
"""
|
|
||||||
test_verify.py - Extension badge count verification test
|
|
||||||
|
|
||||||
Verifies Rentgen's core functionality: counting third-party domains.
|
|
||||||
Tests two scenarios:
|
|
||||||
1. Site without third-party domains (news.ycombinator.com) → badge = 0
|
|
||||||
2. Site with third-party domains (pudelek.pl) → badge > 0
|
|
||||||
"""
|
|
||||||
|
|
||||||
import sys
|
|
||||||
import time
|
|
||||||
import subprocess
|
|
||||||
import os
|
|
||||||
import signal
|
|
||||||
|
|
||||||
|
|
||||||
def is_tty():
|
|
||||||
"""Check if stdout is a TTY."""
|
|
||||||
return sys.stdout.isatty()
|
|
||||||
|
|
||||||
|
|
||||||
def red(text):
|
|
||||||
"""Return red text if TTY, otherwise plain text."""
|
|
||||||
if is_tty():
|
|
||||||
return f"\033[91m{text}\033[0m"
|
|
||||||
return text
|
|
||||||
|
|
||||||
|
|
||||||
def start_xvfb():
|
|
||||||
"""Start Xvfb virtual X server. Returns PID."""
|
|
||||||
xvfb = subprocess.Popen(
|
|
||||||
["Xvfb", ":99", "-screen", "0", "1024x768x24"],
|
|
||||||
stdout=subprocess.DEVNULL,
|
|
||||||
stderr=subprocess.DEVNULL
|
|
||||||
)
|
|
||||||
os.environ["DISPLAY"] = ":99"
|
|
||||||
time.sleep(2)
|
|
||||||
return xvfb.pid
|
|
||||||
|
|
||||||
|
|
||||||
def start_webext():
|
|
||||||
"""Start web-ext with Marionette enabled. Returns PID."""
|
|
||||||
webext = subprocess.Popen(
|
|
||||||
["npx", "web-ext", "run",
|
|
||||||
"--arg=-marionette",
|
|
||||||
"--arg=--marionette-port",
|
|
||||||
"--arg=2828"],
|
|
||||||
stdout=subprocess.DEVNULL,
|
|
||||||
stderr=subprocess.DEVNULL
|
|
||||||
)
|
|
||||||
return webext.pid
|
|
||||||
|
|
||||||
|
|
||||||
def test_badge_count():
|
|
||||||
"""Test badge count for sites with/without third-party domains. Returns (success, results_dict)."""
|
|
||||||
try:
|
|
||||||
from marionette_driver.marionette import Marionette
|
|
||||||
|
|
||||||
# Wait for Firefox to start
|
|
||||||
time.sleep(10)
|
|
||||||
|
|
||||||
# Connect to Marionette
|
|
||||||
client = Marionette(host='localhost', port=2828)
|
|
||||||
client.start_session()
|
|
||||||
|
|
||||||
# Load test library
|
|
||||||
test_lib_path = os.path.join(os.path.dirname(__file__), 'test-lib.js')
|
|
||||||
with open(test_lib_path, 'r') as f:
|
|
||||||
test_lib = f.read()
|
|
||||||
|
|
||||||
results = {}
|
|
||||||
|
|
||||||
# Test 1: Site without third-party domains
|
|
||||||
print(" Testing news.ycombinator.com (expected: 0 third-party domains)...")
|
|
||||||
client.navigate("https://news.ycombinator.com")
|
|
||||||
time.sleep(5) # Wait for page load and tracking detection
|
|
||||||
|
|
||||||
badge_count_hn = client.execute_script(
|
|
||||||
test_lib + "\nreturn testBadgeCount();",
|
|
||||||
script_timeout=10000
|
|
||||||
)
|
|
||||||
results['hn'] = badge_count_hn
|
|
||||||
print(f" → Badge count: {badge_count_hn}")
|
|
||||||
|
|
||||||
# Test 2: Site with third-party domains
|
|
||||||
print(" Testing pudelek.pl (expected: >0 third-party domains)...")
|
|
||||||
client.navigate("https://pudelek.pl")
|
|
||||||
time.sleep(10) # Wait longer for page load and tracking detection
|
|
||||||
|
|
||||||
badge_count_pudelek = client.execute_script(
|
|
||||||
test_lib + "\nreturn testBadgeCount();",
|
|
||||||
script_timeout=10000
|
|
||||||
)
|
|
||||||
results['pudelek'] = badge_count_pudelek
|
|
||||||
print(f" → Badge count: {badge_count_pudelek}")
|
|
||||||
|
|
||||||
client.close()
|
|
||||||
|
|
||||||
# Verify results
|
|
||||||
if badge_count_hn is None or badge_count_pudelek is None:
|
|
||||||
return False, "Test timed out or failed to get badge count"
|
|
||||||
|
|
||||||
if badge_count_hn == 0 and badge_count_pudelek > 0:
|
|
||||||
return True, results
|
|
||||||
else:
|
|
||||||
return False, f"Unexpected results: HN={badge_count_hn} (expected 0), Pudelek={badge_count_pudelek} (expected >0)"
|
|
||||||
|
|
||||||
except Exception as e:
|
|
||||||
return False, str(e)
|
|
||||||
|
|
||||||
|
|
||||||
def cleanup(xvfb_pid, webext_pid):
|
|
||||||
"""Kill processes."""
|
|
||||||
try:
|
|
||||||
os.kill(webext_pid, signal.SIGTERM)
|
|
||||||
except:
|
|
||||||
pass
|
|
||||||
try:
|
|
||||||
os.kill(xvfb_pid, signal.SIGTERM)
|
|
||||||
except:
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
def main():
|
|
||||||
"""Main test."""
|
|
||||||
print("Starting Rentgen badge count verification test...")
|
|
||||||
print()
|
|
||||||
|
|
||||||
xvfb_pid = start_xvfb()
|
|
||||||
webext_pid = start_webext()
|
|
||||||
|
|
||||||
success, result = test_badge_count()
|
|
||||||
|
|
||||||
cleanup(xvfb_pid, webext_pid)
|
|
||||||
|
|
||||||
print()
|
|
||||||
if not success:
|
|
||||||
print(red(f"FAIL: {result}"))
|
|
||||||
return 1
|
|
||||||
|
|
||||||
print(f"PASS: Badge count test succeeded!")
|
|
||||||
print(f" - news.ycombinator.com: {result['hn']} third-party domains")
|
|
||||||
print(f" - pudelek.pl: {result['pudelek']} third-party domains")
|
|
||||||
return 0
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
try:
|
|
||||||
sys.exit(main())
|
|
||||||
except KeyboardInterrupt:
|
|
||||||
sys.exit(130)
|
|
||||||
except Exception as e:
|
|
||||||
print(red(f"ERROR: {e}"))
|
|
||||||
sys.exit(1)
|
|
||||||
Loading…
x
Reference in New Issue
Block a user