Extension Overview¶
The Certana Browser Extension enables on-the-fly image verification directly within any website, built with Vue.js 3 and the WXT framework.
Key Features¶
🔍 In-Browser Verification¶
- Right-click context menu on images
- Inline result display
- No page reload required
🎨 User Interface¶
- Popup for quick verification
- Settings panel for API key management
- Verification history
- Dark mode support
🔐 Security¶
- API key storage (encrypted in browser)
- CORS-compliant requests
- No data logging on extension
📊 Real-Time Results¶
- Confidence scores
- Watermark detection
- Blockchain verification
- Detailed breakdown
Supported Browsers¶
- ✅ Chrome (90+)
- ✅ Edge (90+)
- ✅ Firefox (88+)
- ✅ Opera (76+)
Project Structure¶
browser/
├── src/
│ ├── entrypoints/ # Extension entry points
│ │ ├── background.ts # Service worker
│ │ ├── content.ts # Content script
│ │ └── popup/ # Popup UI
│ │ ├── Popup.vue # Main popup
│ │ ├── views/
│ │ │ ├── VerifyView.vue
│ │ │ ├── SettingsView.vue
│ │ │ ├── HistoryView.vue
│ │ │ └── AboutView.vue
│ │ └── main.ts
│ │
│ ├── components/ # Shared components
│ │ ├── ImageVerifier.vue # Verification UI
│ │ ├── ResultDisplay.vue # Results view
│ │ ├── SettingsForm.vue
│ │ ├── LoadingSpinner.vue
│ │ └── ...
│ │
│ ├── api-service.ts # Backend API client
│ ├── storage-service.ts # Browser storage
│ ├── types.ts # TypeScript types
│ └── styles.css # Global styles
│
├── public/ # Static assets
│ └── icon/ # Extension icons
│
├── wxt.config.ts # WXT configuration
├── manifest.json # Extension manifest
├── tsconfig.json
├── package.json
└── README.md
Architecture¶
User Interaction
├─► Right-click context menu
├─► Popup window
└─► Settings panel
│
▼
Content Script (content.ts)
- Injects UI into page
- Handles user interactions
- Communicates with background
│
▼
Background Service Worker (background.ts)
- Manages state
- Communicates with popup
- Handles storage
│
▼
API Service (api-service.ts)
- Sends requests to backend
- Manages authentication
│
▼
Certana Backend API
- Verifies images
- Returns results
Key Components¶
Popup (popup/Popup.vue)¶
Main popup interface with multiple views:
<template>
<div class="popup">
<header>
<img src="@/public/icon/logo.png" alt="Certana" />
<h1>Certana</h1>
</header>
<component :is="currentView" />
<footer>
<button @click="showSettings">Settings</button>
</footer>
</div>
</template>
Image Verifier Component¶
<ImageVerifier :image-url="selectedImage" @verify="handleVerify" />
Handles: - Image selection - Upload to backend - Display verification in progress - Show results
Result Display Component¶
<ResultDisplay
:result="verificationResult"
:loading="isLoading"
/>
Shows: - Verdict (Authentic/Forged/Unknown) - Confidence score - Watermark detection - Blockchain status - Detailed breakdown
API Integration¶
CertanaApiService¶
export class CertanaApiService {
constructor(apiEndpoint: string, apiKey: string);
// Validate API key
validateApiKey(): Promise<ApiKeyValidation>;
// Verify image
verifyImage(imageBlob: Blob): Promise<VerifyResponse>;
// Get verification history
getHistory(page: number): Promise<VerificationHistory>;
}
Storage Service¶
export class StorageService {
// Get stored API key
getApiKey(): Promise<string | null>;
// Save API key (encrypted)
saveApiKey(key: string): Promise<void>;
// Get verification history
getHistory(): Promise<VerificationLog[]>;
// Save verification to history
addToHistory(log: VerificationLog): Promise<void>;
}
Manifest Configuration¶
{
"manifest_version": 3,
"name": "Certana - Image Verification",
"description": "Verify images on any website with blockchain and ML",
"version": "1.0.0",
"permissions": [
"storage",
"contextMenus",
"webRequest"
],
"host_permissions": [
"<all_urls>"
],
"background": {
"service_worker": "background.ts"
},
"action": {
"default_popup": "popup/index.html",
"default_title": "Verify with Certana"
},
"context_menus": [
{
"id": "verify-image",
"title": "Verify with Certana",
"contexts": ["image"]
}
]
}
Content Script (content.ts)¶
Injected into every webpage:
// Listen for context menu clicks
chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
if (request.action === 'verify-image') {
// Get image URL from context
const imageUrl = request.imageUrl;
// Send to popup
chrome.runtime.sendMessage({
action: 'show-results',
results: verificationResults,
});
}
});
// Right-click menu handler
chrome.contextMenus.onClicked.addListener((info, tab) => {
if (info.menuItemId === 'verify-image') {
// Open popup with image
chrome.action.openPopup();
}
});
Background Service Worker (background.ts)¶
// Handle messages from popup
chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
if (message.type === 'verify-image') {
verifyImage(message.imageBlob).then(result => {
sendResponse({ success: true, data: result });
});
}
});
// Context menu handler
chrome.contextMenus.create({
id: 'verify-image',
title: 'Verify with Certana',
contexts: ['image'],
});
Storage¶
Uses Chrome Storage API:
// Save API key
chrome.storage.sync.set({ 'api_key': encryptedKey });
// Retrieve API key
chrome.storage.sync.get(['api_key'], (result) => {
const apiKey = decryptKey(result.api_key);
});
// Save verification history
chrome.storage.local.set({ 'history': [...] });
Permissions¶
| Permission | Why |
|---|---|
storage |
Store API key and history |
contextMenus |
Right-click menu |
<all_urls> |
Access images on any site |
Security Considerations¶
API Key Storage¶
- Stored encrypted in chrome.storage
- Never sent to any third party
- User can revoke at any time
Data Privacy¶
- Verification results NOT stored on extension
- Optional local history storage
- No tracking or analytics
CORS Handling¶
- Uses proper CORS headers
- Browser enforces same-origin policy
- API must include
Access-Control-Allow-Origin