Claude Skills Guide

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:

// 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:

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:

  1. Test with chrome://inspect/#extensions for background page debugging
  2. Use chrome://webrtc-internals for WebRTC stream inspection
  3. Check console for MediaStream errors
  4. 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:

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