Building a screen sharing Chrome extension requires understanding Chrome’s desktop capture APIs, permission models, and the constraints imposed by Manifest V3. This guide covers the technical implementation for developers and power users who want to integrate screen sharing into their browser-based workflows.
Understanding Chrome’s Desktop Capture API
Chrome provides the chrome.desktopCapture API for capturing screen, windows, and tabs. This API powers built-in features like Google Meet screen sharing and is the foundation for any screen sharing extension.
The API offers several capture sources:
- screen: Entire display screens
- window: Individual application windows
- tab: Specific browser tabs
- audio: System or tab audio (with limitations)
// Request screen capture permission
async function startScreenShare() {
const sources = await chrome.desktopCapture.getDesktopSources({
types: ['screen', 'window'],
thumbnailSize: { width: 320, height: 180 }
});
// Display source picker UI to user
return sources;
}
The getDesktopSources() method returns an array of DesktopCaptureSource objects, each containing an ID, name, thumbnail, and type. Your extension must present these to users for selection.
Manifest V3 Permission Requirements
Manifest V3 requires declaring specific permissions in your extension manifest:
{
"manifest_version": 3,
"name": "Screen Share Pro",
"version": "1.0.0",
"permissions": [
"desktopCapture"
],
"host_permissions": [
"<all_urls>"
]
}
Note that desktopCapture is a permission, not a host permission. However, if your extension needs to send captured streams to specific domains, you’ll need appropriate host permissions for those URLs.
Building the Capture Flow
The typical screen sharing workflow involves requesting sources, obtaining a media stream, and processing or transmitting it:
// Complete capture workflow
async function captureTab(tabId) {
// Step 1: Get stream from specific tab
const stream = await navigator.mediaDevices.getUserMedia({
audio: false,
video: {
mandatory: {
chromeMediaSource: 'tab',
chromeMediaSourceId: tabId
}
}
});
return stream;
}
// Capture with audio from system
async function captureWithAudio(sourceId) {
const stream = await navigator.mediaDevices.getUserMedia({
audio: {
mandatory: {
chromeMediaSource: 'desktop',
chromeMediaSourceId: sourceId
}
},
video: {
mandatory: {
chromeMediaSource: 'desktop',
chromeMediaSourceId: sourceId
}
}
});
return stream;
}
The chromeMediaSource and chromeMediaSourceId constraints are Chrome-specific and allow targeting specific capture sources obtained through the desktopCapture API.
Handling Stream Constraints
Developers should understand the constraints available for different capture types:
const captureOptions = {
video: {
// Frame rate - reduce for lower bandwidth
frameRate: 30,
// Dimensions - match source or specify custom
width: { ideal: 1920 },
height: { ideal: 1080 },
// Display surface type (for screen share)
displaySurface: 'monitor' // 'monitor', 'window', 'browser'
},
audio: {
// Echo cancellation helps with feedback
echoCancellation: { ideal: true },
// Noise suppression for clearer audio
noiseSuppression: { ideal: true }
}
};
For tab capture, the displaySurface constraint doesn’t apply. Screen capture supports monitor (entire screen), window (specific window), and browser (specific tab).
Security Considerations
Screen sharing extensions handle sensitive data, so security is critical:
User Consent: Always display clear UI showing what is being shared. Chrome automatically shows a system prompt, but your extension should reinforce this.
Data Handling: Streams are MediaStream objects. You cannot access raw pixels directly—video frames are processed by the browser’s media pipeline. If you need to analyze frames, use VideoFrame API or canvas capture:
// Capture frame to canvas for processing
function captureFrame(videoElement) {
const canvas = document.createElement('canvas');
canvas.width = videoElement.videoWidth;
canvas.height = videoElement.videoHeight;
const ctx = canvas.getContext('2d');
ctx.drawImage(videoElement, 0, 0);
return canvas.toDataURL('image/png');
}
Storage Permissions: If your extension saves recordings, use the File System Access API or chrome.downloads API with proper permission checks.
Common Implementation Patterns
Recording to Local File
async function startRecording(stream) {
const mediaRecorder = new MediaRecorder(stream, {
mimeType: 'video/webm;codecs=vp9'
});
const chunks = [];
mediaRecorder.ondataavailable = (e) => chunks.push(e.data);
mediaRecorder.onstop = () => {
const blob = new Blob(chunks, { type: 'video/webm' });
// Save or process the recording
};
mediaRecorder.start();
return mediaRecorder;
}
Streaming to WebRTC
For real-time screen sharing to a remote server:
async function streamToPeerConnection(stream, peerConnection) {
stream.getTracks().forEach(track => {
peerConnection.addTrack(track, stream);
});
const offer = await peerConnection.createOffer();
await peerConnection.setLocalDescription(offer);
return offer;
}
Extension Architecture Recommendations
For production screen sharing extensions, structure your code with clear separation:
- popup.js: Handles user-initiated capture requests
- content-script.js: Manages in-page video elements for preview
- background.js: Coordinates capture sessions and maintains state
- utils/: Shared utilities for stream processing
Use Chrome’s message passing API to communicate between components:
// From popup to background
chrome.runtime.sendMessage({
action: 'startCapture',
sourceId: selectedSource.id
}, response => {
console.log('Capture started:', response.streamId);
});
Testing and Debugging
Debug screen sharing extensions using Chrome DevTools:
- Test with
chrome://inspect/#extensionsfor background page debugging - Use chrome://webrtc-internals for WebRTC stream inspection
- Check console for MediaStream errors
- Verify permissions in chrome://extensions
Common issues include missing permissions, HTTPS requirement for getUserMedia, and incorrect MIME types for MediaRecorder.
Use Cases for Developers
Screen sharing extensions serve various developer workflows:
- Bug reporting: Capture reproduction steps automatically
- Documentation: Generate walkthrough videos for projects
- Code review: Share specific windows during pair programming
- Training: Create in-browser tutorials
- Remote collaboration: Integrate with custom communication tools
Building your own extension gives you control over the capture experience, storage options, and integration points that off-the-shelf solutions may not provide.
Built by theluckystrike — More at zovo.one