Browser Extensions Integration
Build powerful browser extensions using JSON-RPC for seamless communication
On this page
Overview
Browser extensions provide powerful ways to enhance web applications, and JSON-RPC offers an excellent protocol for communication between extension components and web services. This guide covers how to implement JSON-RPC in browser extensions for Chrome, Firefox, and Safari.
JSON-RPC is particularly well-suited for browser extensions because:
- It provides a standardized way to communicate between background scripts, content scripts, and popup interfaces
- It enables structured communication with backend services that your extension might interact with
- The lightweight format is ideal for the limited resources available to browser extensions
- Version compatibility is easy to maintain across extension updates
Extension Architecture with JSON-RPC
Typical Extension Components
Background Script
Acts as a JSON-RPC server, processing requests from content scripts and popup UI
Content Scripts
JSON-RPC clients that send requests to the background script
Popup/Options UI
Another JSON-RPC client that communicates with the background script
Communication Flow
In a typical browser extension that uses JSON-RPC:
- Content scripts inject into web pages and monitor for specific actions
- When an action is detected, the content script sends a JSON-RPC request to the background script
- The background script processes the request and returns a JSON-RPC response
- The popup UI can also send JSON-RPC requests to fetch state or trigger actions
Tip: Use the Chrome Extensions messaging API with JSON-RPC as the payload format for consistent, well-structured communication between extension components.
Chrome Extensions Implementation
Here's how to implement JSON-RPC in a Chrome extension:
1. Set up the manifest.json
{
"manifest_version": 3,
"name": "JSON-RPC Example Extension",
"version": "1.0",
"description": "Example Chrome extension using JSON-RPC",
"background": {
"service_worker": "background.js"
},
"content_scripts": [
{
"matches": ["<all_urls>"],
"js": ["content.js"]
}
],
"action": {
"default_popup": "popup.html"
},
"permissions": ["storage"]
}
2. Implement the Background Script (JSON-RPC Server)
// background.js
const methods = {
// Example method that stores data
'data.save': async (params) => {
const { key, value } = params;
return new Promise((resolve) => {
chrome.storage.local.set({ [key]: value }, () => {
resolve({ success: true });
});
});
},
// Example method that retrieves data
'data.get': async (params) => {
const { key } = params;
return new Promise((resolve) => {
chrome.storage.local.get([key], (result) => {
resolve({ value: result[key] });
});
});
}
};
// Handle JSON-RPC messages
chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
// Validate JSON-RPC request format
if (!request.jsonrpc || request.jsonrpc !== '2.0' || !request.method) {
sendResponse({
jsonrpc: '2.0',
error: { code: -32600, message: 'Invalid Request' },
id: request.id
});
return true;
}
// Check if method exists
if (!methods[request.method]) {
sendResponse({
jsonrpc: '2.0',
error: { code: -32601, message: 'Method not found' },
id: request.id
});
return true;
}
// Process the method and send response
methods[request.method](request.params)
.then(result => {
sendResponse({
jsonrpc: '2.0',
result,
id: request.id
});
})
.catch(err => {
sendResponse({
jsonrpc: '2.0',
error: { code: -32603, message: 'Internal error', data: err.message },
id: request.id
});
});
// Return true to indicate we'll send a response asynchronously
return true;
});
3. Implement the Content Script (JSON-RPC Client)
// content.js
function sendJsonRpcRequest(method, params) {
return new Promise((resolve, reject) => {
const request = {
jsonrpc: '2.0',
method,
params,
id: Date.now().toString()
};
chrome.runtime.sendMessage(request, response => {
if (!response) {
reject(new Error('No response from background script'));
return;
}
if (response.error) {
reject(new Error(response.error.message));
return;
}
resolve(response.result);
});
});
}
// Example usage
async function saveData() {
try {
const result = await sendJsonRpcRequest('data.save', {
key: 'userPreference',
value: 'dark-mode'
});
console.log('Data saved:', result);
} catch (error) {
console.error('Error saving data:', error);
}
}
Security Considerations
Input Validation
Always validate JSON-RPC parameters to prevent injection attacks. Never trust data coming from content scripts that could be manipulated by malicious websites.
Method Access Control
Implement access control for JSON-RPC methods. Not all methods should be accessible from content scripts.
Data Sanitization
Sanitize any data retrieved from web pages before processing it through your JSON-RPC methods.
Cross-Origin Considerations
Be mindful of cross-origin requests when your extension interacts with external services using JSON-RPC.
Warning: Always assume that content scripts operate in a hostile environment. Implement proper validation and sanitization for all JSON-RPC communication.
Example Projects
Check out these example browser extensions that use JSON-RPC: