How It Works
Understanding the PRIV Chrome extension architecture and data flow.
How It Works
The PRIV extension uses Chrome's Manifest V3 architecture to collect, process, and monetize your browsing data while maintaining privacy.
Architecture Overview
The extension consists of three main components that work together.
graph TD
subgraph "Chrome Extension"
SW[Service Worker<br/>Background Script]
CS[Content Scripts<br/>Data Collection]
PU[Popup UI<br/>React App]
end
subgraph "Storage"
LS[Local Storage<br/>chrome.storage]
end
subgraph "External"
API[PRIV API]
WL[Web3 Wallet]
end
CS -->|Page Data| SW
SW -->|Settings| CS
PU <-->|Messages| SW
SW <-->|Data| LS
SW -->|Batch Submit| API
PU <-->|Connect| WL
API -->|Earnings| SWManifest V3 Architecture
The extension uses Chrome's latest Manifest V3 standard for improved security and performance.
What is Manifest V3?
Manifest V3 is Chrome's extension platform that provides:
- Service Workers: Background scripts that wake on demand
- Declarative APIs: Better privacy controls
- Reduced Permissions: More granular access
- Improved Security: Stricter content security policies
Key Files
extensions/chrome/
public/
manifest.json # Extension configuration
src/
background/
service-worker.ts # Background service worker
content/
content-script.ts # Injected into pages
popup/
index.tsx # Popup React app
components/ # UI components
lib/
collector.ts # Data collection utilities
security.ts # Security helpers
wallet.ts # Wallet integration
sync.ts # Data synchronizationService Worker (Background Script)
The service worker is the brain of the extension. It runs in the background and coordinates all operations.
Responsibilities
| Task | Description |
|---|---|
| Message Handling | Routes messages between components |
| Data Processing | Processes and batches collected data |
| API Communication | Submits data and fetches earnings |
| Alarm Management | Schedules periodic tasks |
| Cache Management | Maintains data cache for performance |
Message Types
The service worker handles these message types:
type MessageType =
| 'GET_SETTINGS' // Retrieve current settings
| 'UPDATE_SETTINGS' // Update user settings
| 'GET_EARNINGS' // Fetch earnings data
| 'GET_STATS' // Fetch user statistics
| 'GET_BALANCE' // Fetch token balance
| 'CONNECT_WALLET' // Initiate wallet connection
| 'DISCONNECT_WALLET' // Disconnect wallet
| 'DATA_COLLECTED' // New data from content script
| 'PAGE_VISIT' // Page visit event
| 'SCROLL_DEPTH' // Scroll tracking event
| 'AD_IMPRESSION' // Ad detection event
| 'CLAIM_EARNINGS' // Claim pending earnings
| 'FLUSH_QUEUE' // Force data submission
| 'REQUEST_SYNC'; // Trigger sync with backendAlarm System
The service worker uses Chrome alarms for scheduled tasks:
| Alarm | Interval | Purpose |
|---|---|---|
batchSubmit | 5 minutes | Submit collected data |
retryQueue | 1 minute | Retry failed submissions |
refreshCache | 5 minutes | Update cached data |
privSync | 5 minutes | Sync with dashboard |
Content Script
Content scripts run in the context of web pages and collect data based on user preferences.
Data Collection Flow
sequenceDiagram
participant Page as Web Page
participant CS as Content Script
participant SW as Service Worker
participant Storage as Local Storage
Page->>CS: Page Load Event
CS->>SW: Get Settings
SW-->>CS: User Preferences
alt Data Sharing Enabled
CS->>CS: Collect Page Data
CS->>CS: Anonymize URLs/Titles
CS->>SW: Send PAGE_VISIT
SW->>Storage: Store Entry
end
Page->>CS: Scroll Event
CS->>SW: Send SCROLL_DEPTH
Page->>CS: Page Unload
CS->>SW: Send Exit DataWhat Gets Collected
Based on enabled data types, the content script collects:
interface PageVisitData {
url: string; // Anonymized URL (no query params)
domain: string; // Website domain
title: string; // Sanitized page title
category: string; // Detected category (social, shopping, etc.)
enterTime: number; // Timestamp when page opened
exitTime?: number; // Timestamp when page closed
timeSpent?: number; // Seconds on page
scrollDepth?: number; // Maximum scroll percentage
}Excluded URLs
The content script automatically excludes:
- Browser internal pages (
chrome://,about:) - Extension pages (
chrome-extension://) - Local files (
file://) - Sensitive domains (banking, healthcare, email)
Popup UI Components
The popup provides a React-based user interface for managing the extension.
Component Structure
popup/
App.tsx # Main app with routing
components/
Header.tsx # Wallet status and balance
Dashboard.tsx # Main earnings view
DataTypesPanel.tsx # Data type toggles
EarningsCard.tsx # Current earnings display
EarningsHistory.tsx # Weekly earnings chart
WalletConnect.tsx # Wallet connection UI
Settings.tsx # Settings page
DataToggle.tsx # Individual data type toggleState Management
The popup manages state through Chrome's messaging system:
// Fetch settings from background
const response = await chrome.runtime.sendMessage({
type: 'GET_SETTINGS'
});
// Update settings
await chrome.runtime.sendMessage({
type: 'UPDATE_SETTINGS',
payload: { dataSharingEnabled: true }
});Data Flow Diagram
Complete data flow from collection to earnings.
flowchart LR
subgraph Collection
A[Page Visit] --> B[Content Script]
B --> C{Enabled?}
C -->|Yes| D[Anonymize]
C -->|No| E[Discard]
D --> F[Local Storage]
end
subgraph Processing
F --> G[Batch Queue]
G -->|5 min| H[Deduplicate]
H --> I[Submit Batch]
end
subgraph Backend
I --> J[PRIV API]
J --> K[Aggregation]
K --> L[Marketplace]
end
subgraph Earnings
L --> M[Sale Event]
M --> N[Calculate Share]
N --> O[Credit Balance]
O --> P[Withdraw to Wallet]
endSecurity Model
The extension implements multiple security layers.
Message Validation
All messages are validated before processing:
function validateMessage(
message: unknown,
sender: chrome.runtime.MessageSender
): { isValid: boolean; error?: string } {
// Validate sender is from our extension
if (sender.id !== chrome.runtime.id) {
return { isValid: false, error: 'Invalid sender' };
}
// Validate message structure
if (!message || typeof message !== 'object') {
return { isValid: false, error: 'Invalid format' };
}
// Check message type
if (!isValidMessageType(message.type)) {
return { isValid: false, error: 'Invalid type' };
}
return { isValid: true };
}Rate Limiting
External messages are rate limited:
const externalMessageRateLimiter = new RateLimiter(
10, // max requests
60000 // per minute
);Content Security Policy
The extension enforces strict CSP:
{
"content_security_policy": {
"extension_pages": "script-src 'self'; object-src 'self'"
}
}Offline Support
The extension works offline and queues data for later submission.
Queue System
interface QueueEntry {
id: string; // Unique entry ID
data: CollectedDataEntry;// The data to submit
attempts: number; // Retry count
createdAt: number; // When queued
lastAttempt: number | null; // Last retry time
}Retry Logic
- Data is collected and stored locally
- Every 5 minutes, batch submission is attempted
- If offline, data is added to retry queue
- Retry queue processes every 1 minute
- After 10 failed attempts, data is discarded
Privacy Guarantees
What Advertisers See
Aggregated, anonymized data:
{
"segment": "DeFi Power Users",
"count": 1247,
"avgSessionsPerWeek": "5-10",
"topCategories": ["finance", "productivity"],
"avgTimeOnPage": "30-60 seconds"
}What Advertisers Never See
- Your wallet address
- Specific URLs you visited
- Page content or titles
- Your browsing history timeline
- Any personally identifiable information
Next Steps
- Data Types - Available data categories
- Privacy & Security - Security details
- Development - Build and contribute