Firefox browser add-on development

Our company is engaged in the development, support and maintenance of sites of any complexity. From simple one-page sites to large-scale cluster systems built on micro services. Experience of developers is confirmed by certificates from vendors.
Development and maintenance of all types of websites:
Informational websites or web applications
Business card websites, landing pages, corporate websites, online catalogs, quizzes, promo websites, blogs, news resources, informational portals, forums, aggregators
E-commerce websites or web applications
Online stores, B2B portals, marketplaces, online exchanges, cashback websites, exchanges, dropshipping platforms, product parsers
Business process management web applications
CRM systems, ERP systems, corporate portals, production management systems, information parsers
Electronic service websites or web applications
Classified ads platforms, online schools, online cinemas, website builders, portals for electronic services, video hosting platforms, thematic portals

These are just some of the technical types of websites we work with, and each of them can have its own specific features and functionality, as well as be customized to meet the specific needs and goals of the client.

Our competencies:
Development stages
Latest works
  • image_website-b2b-advance_0.png
    B2B ADVANCE company website development
    1212
  • image_web-applications_feedme_466_0.webp
    Development of a web application for FEEDME
    1161
  • image_websites_belfingroup_462_0.webp
    Website development for BELFINGROUP
    852
  • image_ecommerce_furnoro_435_0.webp
    Development of an online store for the company FURNORO
    1041
  • image_crm_enviok_479_0.webp
    Development of a web application for Enviok
    822
  • image_bitrix-bitrix-24-1c_fixper_448_0.png
    Website development for FIXPER company
    815

Firefox Add-on Development

Firefox Add-ons are based on WebExtensions API — the same specification as Chrome Extensions. Most Chrome extensions can be ported to Firefox with minimal changes. However, there are differences in details: API support, signing procedure, extension engine.

Firefox vs Chrome differences

Aspect Firefox Chrome
API namespace browser.* (Promise) + chrome.* chrome.* (Callback)
Manifest MV2 and MV3 (MV3 added in Firefox 109+) MV3 only (MV2 deprecated)
Background Persistent background page (MV2) or SW (MV3) Service Worker only
Signing Required via AMO Not required
browser_style Supported Not supported

Manifest V2 (Firefox — most stable variant)

{
  "manifest_version": 2,
  "name": "My Firefox Add-on",
  "version": "1.0.0",
  "description": "Add-on description",
  "permissions": [
    "storage",
    "tabs",
    "activeTab",
    "https://*.example.com/*"
  ],
  "background": {
    "scripts": ["background.js"],
    "persistent": false
  },
  "browser_action": {
    "default_popup": "popup.html",
    "default_icon": {
      "48": "icons/icon48.png",
      "96": "icons/icon96.png"
    }
  },
  "content_scripts": [{
    "matches": ["https://*.target-site.com/*"],
    "js": ["content.js"]
  }],
  "options_ui": {
    "page": "options.html",
    "open_in_tab": false
  }
}

Promise-based API

Firefox supports native Promises in browser.*. The webextension-polyfill polyfill makes code compatible with Chrome:

import browser from 'webextension-polyfill';

// Firefox — native promises
const tabs = await browser.tabs.query({ active: true, currentWindow: true });
const tab = tabs[0];

// Execute script (MV2)
await browser.tabs.executeScript(tab.id, {
  code: 'document.body.style.background = "yellow"',
});

// Storage
await browser.storage.local.set({ key: 'value' });
const result = await browser.storage.local.get('key');

Content Script: limitations and workarounds

In Firefox, Content Scripts run in an isolated world (Xray wrapper) — they don't have direct access to JavaScript objects on the page. For interaction with the page, you need window.postMessage or CustomEvent:

// Content script -> Page script
window.postMessage({ source: 'myExtension', type: 'REQUEST_DATA' }, '*');

// Page script handler
window.addEventListener('message', (e) => {
  if (e.data?.source === 'myExtension' && e.data?.type === 'REQUEST_DATA') {
    window.postMessage({
      source: 'myPage',
      type: 'RESPONSE_DATA',
      payload: window.__MY_APP_STATE__,
    }, '*');
  }
});

Signing and publishing

Firefox requires signing from Mozilla for any extension not distributed through AMO:

# web-ext — official CLI from Mozilla
npm install -g web-ext

# Development with hot reload
web-ext run --source-dir ./dist --firefox-binary "/path/to/firefox"

# Build
web-ext build --source-dir ./dist --artifacts-dir ./artifacts

# Signing (requires AMO API keys)
web-ext sign \
  --source-dir ./dist \
  --api-key $AMO_JWT_ISSUER \
  --api-secret $AMO_JWT_SECRET

To get API keys: addons.mozilla.org/developers/addon/api/key/.

Temporary installation for testing

Without signing, the add-on can only be installed via about:debugging:

  1. Open about:debugging#/runtime/this-firefox
  2. "Load Temporary Add-on"
  3. Select manifest.json
  4. Works until browser restart

For corporate deployment without AMO — use policies.json in Firefox Enterprise.

Firefox specifics: contextualIdentities (containers)

Firefox supports Containers — isolated contexts with separate cookies. Access via API:

const containers = await browser.contextualIdentities.query({});
// { cookieStoreId, name, color, icon }

// Open tab in specific container
await browser.tabs.create({
  url: 'https://example.com',
  cookieStoreId: 'firefox-container-1',
});

Timeline

Firefox Add-on adapted from Chrome extension, with signing and AMO publication — 2–3 additional days on top of ready Chrome extension. New add-on development from scratch — 4–8 days depending on functionality.