Web APIs in Firefox: Notifications, Web Share, File System, Web Locks, and What's Missing
Firefox implements a large set of modern web APIs. Here's a practical overview of APIs that either work differently in Firefox vs Chrome, or that Firefox has ahead of Chrome. Notifications API // Request p
Firefox implements a large set of modern web APIs. Here's a practical overview of APIs that either work differently in Firefox vs Chrome, or that Firefox has ahead of Chrome.
Notifications API
// Request permission
const permission = await Notification.requestPermission();
if (permission === 'granted') {
const notification = new Notification('Title', {
body: 'Notification body',
icon: '/icon.png',
badge: '/badge.png',
tag: 'unique-tag', // Replace existing notifications with same tag
requireInteraction: true // Keep notification visible until dismissed
});
notification.onclick = () => {
window.focus();
notification.close();
};
}
Firefox behavior: Notification permissions are per-site. Firefox doesn't show Chrome's "Should [site] send notifications?" for new sites — it waits for the site to request via requestPermission().
Firefox strict popup blocking: If you call requestPermission() outside of a user gesture (click, key press), Firefox blocks the permission prompt. Chrome shows it anyway.
Web Share API
// Share content to mobile apps
await navigator.share({
title: 'Article title',
text: 'Check out this article',
url: 'https://example.com/article'
});
Firefox Android: Fully supported — shows Android share sheet.
Firefox Desktop: Support was added in Firefox 91+, but limited to supporting apps on the OS. On Windows, it integrates with Windows share. On Linux, share targets are limited.
// Check support
if (navigator.canShare && navigator.canShare({ url: 'https://example.com' })) {
// Share supported for this content
}
Speech Recognition and Synthesis
Speech Synthesis (TTS)
// Text to speech
const utterance = new SpeechSynthesisUtterance('Hello, world!');
utterance.lang = 'en-US';
utterance.rate = 1.0; // 0.1 to 10
utterance.pitch = 1.0; // 0 to 2
utterance.volume = 1.0;
// List voices
const voices = speechSynthesis.getVoices();
utterance.voice = voices.find(v => v.name.includes('Google'));
speechSynthesis.speak(utterance);
Firefox TTS support: Uses OS voices. On Windows, uses Windows SAPI voices. On Linux, uses eSpeak if installed. Voice availability varies by OS.
Speech Recognition
const recognition = new webkitSpeechRecognition(); // Chrome
// Firefox: uses SpeechRecognition (no webkit prefix)
const recognition = new SpeechRecognition();
recognition.lang = 'en-US';
recognition.continuous = false;
recognition.onresult = (event) => {
const transcript = event.results[0][0].transcript;
console.log('Heard:', transcript);
};
recognition.start();
Firefox: Speech Recognition API requires an about:config flag to enable: media.webspeech.recognition.enable = true. Not enabled by default (privacy considerations — sends audio to a speech server).
File System API
File Picker (works in Firefox)
// Show file picker
const fileInput = document.createElement('input');
fileInput.type = 'file';
fileInput.accept = 'image/*';
fileInput.multiple = true;
fileInput.addEventListener('change', () => {
Array.from(fileInput.files).forEach(file => {
console.log(file.name, file.size, file.type);
const reader = new FileReader();
reader.onload = (e) => console.log('Data:', e.target.result.slice(0, 100));
reader.readAsDataURL(file);
});
});
fileInput.click();
File System Access API (showOpenFilePicker)
// Modern API for reading/writing local files
const [fileHandle] = await window.showOpenFilePicker({
types: [{
description: 'JSON files',
accept: { 'application/json': ['.json'] }
}]
});
const file = await fileHandle.getFile();
const contents = await file.text();
console.log(contents);
// Write file
const writable = await fileHandle.createWritable();
await writable.write('new contents');
await writable.close();
Firefox 112+ support: Firefox added File System Access API in version 112. Older Firefox versions don't support showOpenFilePicker. Use a feature detection check.
Web Locks API
Prevent concurrent access to shared resources:
// Acquire an exclusive lock
await navigator.locks.request('resource-key', async (lock) => {
// Only one tab runs this at a time
await doExclusiveWork();
});
// Acquire with timeout
await navigator.locks.request('resource-key', {
ifAvailable: true // Don't wait, return null if locked
}, async (lock) => {
if (!lock) {
console.log('Resource locked, skipping');
return;
}
await doWork();
});
Firefox support: Full support in Firefox 96+. The Web Locks API is useful for preventing duplicate work in multi-tab applications.
Payment Request API
const request = new PaymentRequest(
[{ supportedMethods: 'basic-card' }], // Payment methods
{
total: { label: 'Total', amount: { currency: 'USD', value: '10.00' } },
displayItems: [
{ label: 'Item', amount: { currency: 'USD', value: '10.00' } }
]
}
);
const response = await request.show();
const { methodName, details } = response;
await response.complete('success');
Firefox: Supports Payment Request API. In practice, the "basic-card" method shows a Firefox-native payment form. Third-party payment methods (Google Pay, Apple Pay) require merchant integration.
Idle Detection API
const detector = new IdleDetector();
detector.addEventListener('change', () => {
console.log('User state:', detector.userState); // 'active' or 'idle'
console.log('Screen state:', detector.screenState); // 'locked' or 'unlocked'
});
await detector.start({ threshold: 60_000 }); // Detect after 60s of idle
Firefox 94+: Supports Idle Detection API. Useful for apps that should stop polling or showing notifications when user is away.
Contact Picker API
Pick contacts from the device's contact list:
const contacts = await navigator.contacts.select(
['name', 'email', 'tel'],
{ multiple: true }
);
contacts.forEach(contact => {
console.log(contact.name, contact.email);
});
Firefox: Not yet implemented (as of 2024). This is primarily a mobile API (Android Chrome, iOS Safari support it). Firefox Android doesn't support it.
Badging API
Show a notification badge on the PWA icon:
// Set badge with count
await navigator.setAppBadge(5);
// Clear badge
await navigator.clearAppBadge();
Firefox: Not supported. This API primarily works in Chrome/Edge on desktop and mobile.
Keyboard Map API
// Get physical key names for current keyboard layout
const map = await navigator.keyboard.getLayoutMap();
const key = map.get('KeyQ'); // Returns 'q' for US, 'a' for AZERTY, etc.
Firefox: Supported. Useful for games that should use physical keyboard positions rather than character values.
Summary: Firefox API Support Status
| API | Firefox |
|---|---|
| Notifications | Full |
| Web Share | Desktop (91+), Full on Android |
| Speech Synthesis | Full |
| Speech Recognition | Experimental (flag) |
| File System Access | 112+ |
| Web Locks | 96+ |
| Payment Request | Full |
| Idle Detection | 94+ |
| Contact Picker | Not supported |
| Badging API | Not supported |
| Keyboard Map | Full |
| Web Bluetooth | Not supported |
| Web USB | Not supported |
| Web NFC | Not supported |
Mozilla's stance on sensor APIs (Bluetooth, USB, NFC): Security and privacy concerns. Mozilla hasn't shipped these; they require being near untrusted hardware. This is a deliberate policy difference from Chrome's "ship everything" approach.
Originally published by Dev.to WebDev. Aggregated on AIWithGhost for educational purposes — full credit and traffic to the original publisher.