Update (2026-02-28): Latest full-repository scan baseline is documented in /docs/MAJOR_SCAN_2026-02-28.md; deployment/rollout actions are tracked in /docs/DEPLOYMENT_RUNBOOK.md.
- OS: Windows, macOS, or Linux (Tested on macOS/Linux)
- Node.js: v22.14.0 (Required, see
.nvmrc) - Package Manager: pnpm (Required, see
pnpm-lock.yaml)
- Unzip the source code archive.
- Open a terminal in the root directory (where
package.jsonis located). - Install dependencies:
pnpm install
To generate the production build for Firefox (identical to the submitted XPI):
pnpm run build:firefoxThe built extension will be located in:
./.output/firefox-mv2
You can compare the contents of the .output/firefox-mv2 directory with the submitted extension package to verify they match.
(Original README follows below)
One-click downloads for Google Classroom. This browser extension streamlines file downloads from Google Classroom by injecting smart UI buttons, handling Google Drive authentication quirks, and managing download queues in the background.
| Feature | Description |
|---|---|
| Batch Downloading | "Download All" button that grabs every file from an assignment at once. |
| Google Drive Bypass | Automatically handles Drive's confirmation pages and multi-account authentication. |
| UI Injection | Adds download buttons directly into the Google Classroom interface. |
| Background Processing | Downloads are managed by a service worker that survives tab closures. |
| Anonymous Analytics | Securely reports anonymized usage stats to improve the extension. |
| Per-Tab Control | Enable/disable the extension on individual Classroom tabs via the popup. |
The in-page detection/render system runs on a versioned engine model (V1 legacy,
V2 unified, V3 API-enhanced) controlled by an Engine Mode setting (default:
shadow). It is being migrated to a role-based architecture (Detect / Compute /
Render / Harden) connected by a typed EventBus. Start here:
- docs/ENGINE_ARCHITECTURE.md — what each engine does, every observer/heartbeat, data flow, and a "where do I look when X breaks" reference.
- docs/PRD_ENGINE_REFACTOR.md — the refactor plan: target design, EventBus contract, phased migration, test + doc strategy.
This extension is built with WXT — a modern framework for building browser extensions. WXT was chosen for:
- Auto-imports: No manual import statements for browser APIs.
- Hot Module Replacement (HMR): See changes instantly during development.
- Manifest v3 Ready: Automatic manifest generation with proper service worker handling.
- React Support: First-class React integration via
@wxt-dev/module-react. - Cross-Browser: Build for Chrome and Firefox from the same codebase.
Content scripts inject directly into Google Classroom pages:
| Script | Matches | Purpose |
|---|---|---|
download_all.content.ts |
classroom.google.com/* |
Injects "Download All" buttons and handles batch downloads. |
drive_bypass.content.ts |
drive.google.com/* |
Detects Drive confirmation pages and clicks "Download" automatically. |
comment_frame.content.ts |
classroom.google.com/* |
Handles comment/attachment frames. |
edited_frame.content.ts |
classroom.google.com/* |
Detects edited document states. |
The background.ts service worker:
- Manages Downloads: Tracks pending downloads, handles race conditions, and registers files by URL/ID.
- Auth User Cycling: If Drive returns 403, automatically tries other logged-in Google accounts.
- Drive Bypass Tabs: Opens hidden tabs to click Drive's "Download anyway" buttons.
- Analytics Alarms: Periodically flushes analytics events to the Cloudflare Worker.
The entrypoints/utils/analytics.ts module provides secure, privacy-respecting analytics:
┌─────────────────────────────────────────────────────────────────────┐
│ BROWSER EXTENSION │
│ │
│ ┌─────────────┐ ┌─────────────────────────────────────────┐ │
│ │ Download │───▶│ Analytics.track() │ │
│ │ Event │ │ - Adds browser, OS, version, lang │ │
│ └─────────────┘ │ - Stores in chrome.storage.local │ │
│ │ - Updates local stats (popup UI) │ │
│ └───────────────────┬─────────────────────┘ │
│ │ │
│ ┌──────────────────────────────────────▼───────────────────────┐ │
│ │ Pending Events Queue │ │
│ │ (Persisted in chrome.storage.local) │ │
│ └─────────────────────────────┬────────────────────────────────┘ │
│ │ │
│ ┌────────────────────────────▼────────────────────────────────┐ │
│ │ Flush Triggers (UTC) │ │
│ │ 1. Queue >= batchSize (default: 50) │ │
│ │ 2. Daily randomized window (default 01:00–03:00 UTC) │ │
│ │ 3. Stale events >= 24h │ │
│ │ 4. Time-based thresholds (optional low/mid/high minutes) │ │
│ │ 5. chrome.alarms every 5 minutes │ │
│ └─────────────────────────────┬────────────────────────────────┘ │
│ │ │
└─────────────────────────────────┼───────────────────────────────────┘
│
│ POST /track { events: [...] }
▼
┌─────────────────────────────────────────────────────────────────────┐
│ CLOUDFLARE WORKER (Edge) │
│ cqd-analytics.adhamhaithameid.workers.dev │
└─────────────────────────────────────────────────────────────────────┘
Key Features:
- Batching: Events are queued and sent in batches to reduce network requests.
- Exponential Backoff: Failed flushes retry with increasing delays (1m → 5m → 15m → ... → 24h).
- Poison Pill Protection: Events that fail 5+ times are dropped to prevent infinite retries.
- Dynamic Config: Batch size, daily windows, retry caps, and rate limits are fetched from the Worker's
/configendpoint. - UTC Time Sync: Uses
serverTimeUtcto keep timestamps and windows aligned in UTC. - End-to-End ACK: Events are removed only after the Worker confirms Oracle commit.
- Privacy: No personally identifiable information is collected.
WXT uses a file-system based routing convention. Files in entrypoints/ are automatically recognized:
extension/
├── src/ # Application Logic
│ ├── background/ # Service worker modules (10 files)
│ ├── detection/ # File detection logic
│ ├── download/ # Single download modules
│ ├── download-all/ # Batch download modules
│ ├── i18n/ # Internationalization
│ ├── shared/ # Shared utilities (analytics, state)
│ └── ui/ # UI components & styles
├── entrypoints/
│ ├── background.ts # Service worker entry
│ ├── popup/ # UI popup
│ ├── download_all.content.ts # Content script entry
│ └── ... # Other entry points
├── assets/ # Static assets
├── wxt.config.ts # WXT config
└── package.json # Dependencies
| File Pattern | Purpose |
|---|---|
popup/index.html |
Browser action popup (click on extension icon) |
background.ts |
Service worker (MV3) or background script (MV2) |
*.content.ts |
Content scripts (injected into web pages) |
*.content/index.ts |
Content scripts with multiple files |
- Node.js 20+ (Download)
- pnpm (required)
cd extension
pnpm installpnpm run devThis command:
- Starts Vite in watch mode with HMR.
- Builds the extension to
.output/chrome-mv3-dev/. - Automatically opens a new Chrome instance with the extension pre-loaded.
- Changes to source files are hot-reloaded.
Tip: Keep the Dev Tools console open in the popup or background page to see logs.
pnpm run buildThis creates an optimized production build in .output/chrome-mv3/.
pnpm run zipGenerates a .zip file in .output/ ready for Chrome Web Store submission.
pnpm run dev:firefox # Development
pnpm run build:firefox # Production build
pnpm run zip:firefox # Web Store ZIPThe analytics module sends data to the Cloudflare Worker. The endpoint is configured via VITE_WORKER_URL and read in entrypoints/utils/analytics/constants.ts:
// For LOCAL TESTING:
const VITE_WORKER_URL = 'http://localhost:8787/track';The remote can be disabled entirely by setting WORKER_URL to an empty string.
The extension fetches configuration from the Worker's /config endpoint:
- Batch Size: How many events to send per request.
- Max Daily Requests: Per-extension cap on flushes per UTC day.
- Max Retry: Retry cap before dropping permanently failing events.
- Flush Mode:
next_day(daily UTC window) ortime_based. - Daily Window (UTC): Start hour + window length for randomized daily flush.
- Time Flush Minutes: Low/mid/high thresholds when
time_basedis enabled. - Max Events / Request: Worker-side cap for payload size.
- Cancel Hold Delay: UI safety delay before cancel becomes active.
- Remote Enabled: Backpressure switch (can pause remote analytics).
Configuration is refreshed:
- Once on extension startup.
- Every 3 hours via
chrome.alarms.
The extension requires these permissions (defined in wxt.config.ts):
| Permission | Why It's Needed |
|---|---|
downloads |
Trigger file downloads and track their completion status. |
tabs |
Communicate with content scripts and update extension icon per tab. |
storage |
Persist pending analytics events and local download stats. |
alarms |
Schedule periodic analytics flushes (MV3-safe alternative to setInterval). |
| Host | Why It's Needed |
|---|---|
https://classroom.google.com/* |
Inject content scripts into Classroom pages. |
https://drive.google.com/* |
Handle Drive download confirmations. |
https://drive.usercontent.google.com/* |
Download files from Drive CDN. |
https://accounts.google.com/* |
Handle multi-account authentication. |
- File type (e.g., "pdf", "docx") — not the filename.
- Browser and OS (e.g., "chrome", "windows").
- Extension version.
- Download duration (fast/medium/slow).
- Success or failure (with error type if failed).
- Language (browser locale).
What Is NOT Collected:
- Usernames or emails.
- File names or content.
- Google account details.
- Browsing history outside of download events.
pnpm run compile- Build the extension:
pnpm run build - Open Chrome →
chrome://extensions/ - Enable "Developer mode" (top right)
- Click "Load unpacked"
- Select
.output/chrome-mv3/
This project is part of the Classroom Quick Downloader suite. See the main repository for licensing details.