Ray Shao Back to the room Desktop
ProjectsChrome AI Privacy Extension

← Projects

Chrome AI Privacy Extension

2025 / operational / MSN-002

On this page 7 sections
  1. Why on-device classification
  2. Architecture: Manifest V3 Pipeline & Precedence Chain
  3. Classification pipeline
  4. Policy matrix
  5. Heuristic fallback
  6. Block overlay
  7. Stack

Smart ScreenTime is a Manifest V3 Chrome extension that uses the browser’s built-in Gemini Nano model to classify web content into one of twelve categories, then enforces a per-category policy based on a user-defined focus schedule. No text leaves the device at any point in the loop.

Why on-device classification

The standard approach, extracting page content and sending it to a remote inference endpoint, creates a persistent record of browsing context on a third-party server. Chrome ships with Gemini Nano already installed and exposes it through the experimental Prompt API. Using that instead costs nothing in privacy and adds no latency from a network round-trip. The trade-off is that the model is smaller, so I built a heuristic fallback for cases where the Prompt API is unavailable or returns a confidence score below the configured threshold.

Architecture: Manifest V3 Pipeline & Precedence Chain

┌────────────────────────────────────────────────────────────────────────────────────────┐
│ DOM / TAB CONTENT CONTEXT (Content Script • `document_idle`)                           │
│                                                                                        │
│   ┌───────────────────────────┐   ┌──────────────────────┐   ┌─────────────────────┐   │
│   │ TreeWalker Node Filter    │──►│ Metadata Extractor   │──►│ chrome.runtime      │   │
│   │ Strips nav/footer/sidebars│   │ OG tags, H1, videos  │   │ .sendMessage()      │   │
│   └───────────────────────────┘   └──────────────────────┘   └──────────┬──────────┘   │
└─────────────────────────────────────────────────────────────────────────┼──────────────┘
                                                                          │ IPC Message
                                                                          ▼
┌────────────────────────────────────────────────────────────────────────────────────────┐
│ BACKGROUND SERVICE WORKER (Event-Driven Precedence Chain)                              │
│                                                                                        │
│   [Tier 1: 15-Min Temp Overrides] ──(Hit: Allow)───────────────────────────────────┐   │
│                 │ Miss                                                             │   │
│   [Tier 2: Hostname Allowlist]   ──(Hit: Allow)───────────────────────────────────┤   │
│                 │ Miss                                                             │   │
│   [Tier 3: Hostname Blocklist]   ──(Hit: Block)───────────────────────────────────┤   │
│                 │ Miss                                                             │   │
│   [Tier 4: Dynamic Cache Check]  ──(Hit: Return Cached Decision)──────────────────┤   │
│                 │ Miss                                                             │   │
│                 ▼                                                                  │   │
│   ┌────────────────────────────────────────────────────────────────────────────┐   │   │
│   │ Is Chrome Prompt API Available?                                            │   │   │
│   │    ├── YES ──► Gemini Nano (`temperature: 0.1`) ──► Structured Category JSON   │   │
│   │    └── NO  ──► Heuristic Classifier (Keyword/Domain Matching Engine)       │   │   │
│   └─────────────────────────────────────┬──────────────────────────────────────┘   │   │
│                                         │ Category + Confidence Score              │   │
│                                         ▼                                          │   │
│   ┌────────────────────────────────────────────────────────────────────────────┐   │   │
│   │ Focus / Leisure Policy Matrix (Schedule-Driven Decision Engine)            │   │   │
│   └─────────────────────────────────────┬──────────────────────────────────────┘   │   │
│                                         │ Allow / Block Action                     │   │
│                                         ▼                                          │   │
└─────────────────────────────────────────┼──────────────────────────────────────────┘   │
                                          │                                              │
                                          ▼                                              │
┌────────────────────────────────────────────────────────────────────────────────────────┴┐
│ DOM MODAL INJECTION (When Blocked: Keyboard Trap Modal • CSS Isolation via Manifest V3) │
└─────────────────────────────────────────────────────────────────────────────────────────┘

Classification pipeline

The content script runs at document_idle with a 500ms debounce to handle SPA navigation. It extracts a cleaned text snippet (capped at ~1,200 characters) from semantic content elements (<article>, <main>, [role="main"]) while stripping nav, sidebar, and footer nodes using a TreeWalker with a custom NodeFilter. It also collects Open Graph metadata, the first <h1>, and signals like <video> presence and <code> blocks, then sends the bundle to the background service worker via chrome.runtime.sendMessage.

The service worker resolves each request through a five-tier precedence chain before ever reaching the model:

  1. Temporary allows: 15-minute user overrides stored with an expiry timestamp
  2. Allowlist: permanent hostname exceptions
  3. Blocklist: permanent blocks
  4. Cache: TTL varies by category: 2 hours for social feeds, 48 hours for video and gaming, 7 days for docs and reference content. Cache keys encode hostname:pathBucket:snippetSignature:policyContext to handle pages that change content without changing URL.
  5. Prompt API: Gemini Nano, temperature: 0.1, topK: 1 for deterministic output
On-device inference

The Prompt API call never leaves Chrome. Gemini Nano is already installed on the device; the extension just sends a structured prompt and parses the JSON response. The model returns { category, confidence, reasons }.

Policy matrix

Classification alone doesn’t decide anything; the result passes through a policy matrix that maps each of the twelve categories to allow or block depending on whether the current time is inside the user’s focus window. In focus mode, categories like social/feeds, entertainment, and gaming block; educational/lecture, work/productivity, and news allow. In leisure mode, everything allows except the blocklist.

If the model returns a confidence score below the configured threshold (default 0.75), the extension falls back conservatively: block during focus, allow during leisure.

Heuristic fallback

When the Prompt API is unavailable, during model download or in environments where it hasn’t been enabled, the service worker uses a keyword and domain pattern matcher. Social sites score 0.85 confidence on a domain match alone; a site-plus-keyword combination lands at 0.75 to 0.80; no match returns 0.30 with the unclear category, which the policy matrix treats as block during focus.

Block overlay

When a page is blocked, the content script injects a modal over the page using a stylesheet loaded via web_accessible_resources. The overlay shows the category name, confidence percentage, and the model’s reasoning string. Three actions are available: allow the site for 15 minutes, add the hostname permanently to the allowlist, or dismiss. The modal implements a focus trap with Tab/Shift+Tab cycling, keyboard shortcuts (Esc, Enter, A), and ARIA roles for accessibility. Thumbs-up/thumbs-down feedback buttons store signals for future personalization, though active feedback-driven re-ranking isn’t wired up yet.

Experimental API

The Chrome Prompt API (globalThis.ai.languageModel) is behind an origin trial flag. The extension requires Chrome 127+ with the flag enabled, or enrollment in the origin trial.

Stack

All projectsBack to top