[Guide] How to make a Firefox extension


Recommended Posts

Post your extension in this thread if you make one using this tutorial

Hello, world!

Our extension will be a nice simple one that will pop up a window proclaiming "Hello, world!" after we select it either in a right-click menu, or under the Tools menu. Both of these places are very popular positions, and it's relatively easy to stick something in there.

Let's see what the end result looks like, so you know what to expect. First, here are the two ways to access our extension:

Right-clicking will get us this:

44GPAv.png

The tools menu looks like this:

e7NikA.png

The end result of our extension's efforts:

G4bfxR.png

What it looks like in the extension manager:

xSMm05.png

Clicking on the "About..." in the extension manager will get us this:

AWLnkA.png

Looking inside the XPI

Here's how the extension breaks down in a nutshell, using a pre-made Hello, world! extension as an example:

(You can download it here, just right-click and save, then you can follow along.)

helloworld.xpi is the packaged extension. XPI is just an file format that your browser will recognize as a browser extension. In reality, it's just a zipped up file. So you can rename the XPI to ZIP or even JAR if you want, then open it up using an archive program, like 7-Zip or WinRAR. So, once that's opened up, you'll see:

* chrome

* install.js

* install.rdf

A folder and two files. install.js was all you used to need for the installation, but now that the extension manager has changed (since Firefox 0.9), the install.rdf is used instead. Now, the install.js is used purely for earlier versions of Firefox/bird, Mozilla, and Netscape. If you want to make this extension solely for versions 0.9 and greater of Firefox, then you can omit this file if you'd like. I tend to keep it in because it only take a second to make, and assures a wide audience compatibility. Some extensions simply aren't backwards-compatibile, though, for example my ListZilla extension, since it gathers all information from 0.9's extensions manager. A nice simple "Hello, world!" prompt shouldn't present any problems, though.

If you open up install.js, you'll see that it's very basic, in terms of what you need to modify to make your own install script:

// --- Editable items begin ---

extFullName: 'Hello, world!', // The name displayed to the user (don't include the version)

extShortName: 'helloworld', // The leafname of the JAR file (without the .jar part)

extVersion: '0.1',

extAuthor: 'Eric Hamiter',

extLocaleNames: null, // e.g. ['en-US', 'en-GB']

extSkinNames: null, // e.g. ['classic', 'modern']

extPostInstallMessage: 'Success! Please restart your browser to finish the installation.'

// Set to null for no post-install message

// --- Editable items end ---

So all the hard work is done for you. I'm not going post the rest of the code, but you'll see quite a lengthy amount of work that is fully automated.

Now if you open install.rdf. you'll see this:

<?xml version="1.0"?>

<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#"

xmlns:em="http://www.mozilla.org/2004/em-rdf#">

<Description about="urn:mozilla:install-manifest">

<em:id>{9AA46F4F-4DC7-4c06-97AF-5035170633FE}</em:id>

<em:name>Hello, world!</em:name>

<em:version>0.1</em:version>

<em:description>Displays an alert message via right-click

or Tools menu.</em:description>

<em:creator>Eric Hamiter</em:creator>

<em:homepageURL>http://extensions.roachfiend.com</em:homepageURL>

<em:iconURL>chrome://helloworld/skin/helloworld.png</em:iconURL>

<em:aboutURL>chrome://helloworld/content/about.xul</em:aboutURL>

<em:file>

<Description about="urn:mozilla:extension:file:helloworld.jar">

<em:package>content/helloworld/</em:package>

<em:skin>skin/classic/helloworld/</em:skin>

</Description>

</em:file>

<em:targetApplication>

<Description>

<em:id>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</em:id>

<em:minVersion>0.8</em:minVersion>

<em:maxVersion>1.5</em:maxVersion>

</Description>

</em:targetApplication>

</Description>

</RDF>

Re-configuring your extension's installation

Ok, whoa.. what is all this crap? The first thing you'll see is the <em:id> tag. This is your very own generated id that will separate your extension from anyone else's. There are a few ways to make it. You can either use an online perl script to randomly generate one, or if you use Windows, you can use a program called guidgen, brought to us by Microsoft. How deliciously ironic. Or am I misuing the term irony here? Whatever. So if you download that, then you'll see this when you run it:

gbsxZG.png

So choose 4. Registry Format, then hit New GUID a few times for good measure, then Copy. That's it, now your new spiffy id is in your clipboard. Replace the old one with this, and you're set.

Name, version, description, creator, and homepageURL are all self-explanatory. The iconURL and aboutURL are what shows up if someone right-clicks your extension and chooses "About Extension...". You can leave these blank, it's not mandatory, but it's nice to have a little flash every now and then.

Underneath file, this is standard stuff. Just replace all instances of "helloworld" with your extension name. This is where the installation will try and find your files and folders. If you have any icons, you'll include the skin folder. Again, it's not mandatory.

Target application is what you're gearing this for. The ec8030f7... is unique to Firefox, so leave that alone. The minVersion and maxVersion tags describe what versions of Firefox the extension will be compatibile with. Although as of this writing there is no 1.5 version, and mozilla folk will frown upon you putting in something higher than the current version, this is the easiest way to keep your extensions working through current and future builds. The proper way to do this is to rewrite your extension's maxVersion every time, so you can choose which would be better for you to do.

Chrome is more than a shiny bumper

Ok, now open up the chrome folder. In there you'll find another archived file, helloworld.jar. Open it up and extract the files. You'll now have content and skin folders. Let's explore content first. In there, we have a helloworld folder, and under that, these files:

* about.xul

* contents.rdf

* helloworldOverlay.js

* helloworldOverlay.xul

about.xul is the file you see when you click "About Hello, world!..." in the extensions menu. It's pretty self-explanatory, and you'll see that a nice man named Jed Brown wrote the template for it, so all the hard work has been done for you. Again. So just fill out the info, and that's it.

helloworldOverlay.xul and helloworldOverlay.js are what make things happen. They're the brains behind the outfit, so to speak. And you'll be amazed at how simple they are. Here's helloworldOverlay.xul:

<?xml version="1.0"?>

<overlay id="helloworldOverlay"

xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">

// This imports our javascript.

<script type="application/x-javascript" src="chrome://helloworld/content/helloworldOverlay.js">

</script>

// This is for the right click menu.

<popup id="contentAreaContextMenu">

<menuitem id="helloworld" label="Hello, world!" accesskey="H"

insertafter="context-stop" oncommand="hello();"/>

</popup>

// This is for the Tools menu.

<menupopup id="menu_ToolsPopup">

<menuitem insertafter="devToolsSeparator" label="Hello, world!"

accesskey="H" oncommand="hello();" />

</menupopup>

</overlay>

So all it says to do is to insert the javascript file, helloworldOverlay.js, and to create a context menu entry called Hello, world! accesskey="H" underlines the "H", since it's the first letter that wasn't taken by any other options. insertafter="context-stop" places the option directly underneath the Stop label. oncommand makes it launch the window with the function hello, which is located in the javascript file we imported earlier. The second part of the overlay tells it we also want to place an option in the Tools menu. Same logic as the context menu, just a different place to stick it. Here's what helloworldOverlay.js looks like:

// This is our javascript, which will pop up our message

// in an alert box.

function hello(){

alert("Hello, world!");

}

Now for contents.rdf. This is the file that tells the browser where to store this overlay information. Here's what it looks like:

<?xml version="1.0"?>

<RDF:RDF xmlns:RDF="http://www.w3.org/1999/02/22-rdf-syntax-ns#"

xmlns:chrome="http://www.mozilla.org/rdf/chrome#">

<RDF:Seq RDF:about="urn:mozilla:package:root">

<RDF:li RDF:resource="urn:mozilla:package:helloworld"/>

</RDF:Seq>

<RDF:Seq RDF:about="urn:mozilla:overlays">

<RDF:li RDF:resource="chrome://browser/content/browser.xul"/>

<RDF:li RDF:resource="chrome://navigator/content/navigator.xul"/>

</RDF:Seq>

<RDF:Seq RDF:about="chrome://browser/content/browser.xul">

<RDF:li>chrome://helloworld/content/helloworldOverlay.xul</RDF:li>

</RDF:Seq>

<RDF:Seq about="chrome://navigator/content/navigator.xul">

<RDF:li>chrome://helloworld/content/helloworldOverlay.xul</RDF:li>

</RDF:Seq>

<RDF:Description RDF:about="urn:mozilla:package:helloworld"

chrome:displayName="Hello, world! 0.1"

chrome:author="Eric Hamiter"

chrome:authorURL="mailto:[email protected]"

chrome:name="helloworld"

chrome:extension="true"

chrome:description="Displays an alert message via right-click

or Tools menu.">

</RDF:Description>

</RDF:RDF>

You'll notice the address chrome://browser/content/browser.xul up there. This is mozilla's internal frame of reference. browser is the actual browser, and navigator works for non-Firefox builds, like Netscape or Mozilla. The only part you'd need to modify is the descriptions. The rest of it just implements the extension into the browsers.

Skin that cat

Now let's backtrack to the skin folder. In it, we'll find a few more folders: classic and helloworld. This is just the traditional layout, and if it ain't broke, then hey, don't fix it. In helloworld, we find three files: helloworld.png, helloworldb.png, and a contents.rdf file.

helloworld.png:

ocWoXF.png

helloworldb.png:

uoRtqH.png

These are called from about.xul mentioned previously, for use in the extension menu and the about menu. contents.rdf simply maps out the paths to the skin files, so the only modification you need to change for your own extension is in the last line, which points to the folder helloworld.

Pack it up and try it out

So now that you see how the files work, and where they're packaged, you can modify them to your whims, and try out new things. Once you modify them, just pack them up in reverse order. Using your archive program, you would navigate back up to the chrome folder, and add content and skin into a zipped archive, then rename it to extension.jar. After that, navigate up another folder, and add chrome, install.rdf, and install.js into another zipped archive, then rename it to extension.xpi.

Important: If you decide to use WinRAR for packing your files, make sure you choose the "zip" format in the menu below your filename. The default is set to "rar", and Firefox won't recognize the final xpi file as compatibile if you use the "rar" setting.

You're ready to test it out in your browser now. Open up Firefox, and hit CTRL-O, or Open File. Load up your xpi file, and say yes to the installation. Restart Firefox, and hopefully you'll see your new extension in the menu, and it does whatever you had hoped it would do.

An easier way to re-build

After a while, it gets tiresome to select your files, your folder, archive them, rename them, move them, delete them, rename them... you get my point. If you have 7-Zip installed, you can use the command line feature, so you can have this all fully automated. Here's what you need to do:

Copy C:\Program Files\7-Zip\7z.exe to C:\WINDOWS\system32 (This will put 7z.exe in your system's path, which will make it accessible from the command prompt).

It's a good practice to build your extensions somewhere far away from random scripts and clutter, so create a new folder somewhere and call it whatever your extension is named. Make sure it matches the internal .jar file that you previously referenced in your install.rdf file. You can always rename the final xpi to something more intricate afterward, but for packaging, it's best to keep it simple.

Copy the following script and paste it in a text editor and save it as build.bat in your newly-made folder:

set x=%cd%

md build\chrome

cd chrome

7z a -tzip "%x%.jar" * -r -mx=0

move "%x%.jar" ..\build\chrome

cd ..

copy install.* build

cd build

7z a -tzip "%x%.xpi" * -r -mx=9

move "%x%.xpi" ..\

cd ..

rd build /s/q

Now, you can build or modify your extensions easily. Just use the new folder as your base of creation, so that would contain the install files and chrome folder. Whenever you want to create your new file, just double-click build.bat, and your new extension will pop out in the same folder. Each time you use the build.bat script, it will delete your old file and create a new one.

My Firefox just got completely hosed up

Worst case scenario: upon restarting Firefox, it hangs with a "Firefox is still installing an extension, this may take a minute...". This means you borked it up somehow. Don't panic! A super easy way of uninstalling it without hosing the rest of your **** up is as follows:

Start ? Program Files ? Mozilla Firefox ? Mozilla Firefox (Safe Mode)

Then go to Tools ? Extensions ? [right-click on your extension] ? Uninstall

Restart Firefox, and it'll be gone. Then modify your files and try agaEnsure server compatibilityty

If it works, and you want to put it on your web server, but find out that it won't install directly, and your browser is treating it as "Save File As.." then you need to modify your .htaccess file. You can learn more about it here, but for brevity's sake, you need your server to run on Apache for it to work. If you have no problem modifying the file, here's the information you need to add:

Add this to your .htaccess file:

AddType application/x-xpinstall .xpi

And you should be sAdditional help and informationon

If you want to take a look at any other files I've created, they're on my main extensions page, and I'll list them directly here for convenience as well:

* Allow right click

* Alt text for links

* Always remember password

* Bugmenot

* Goon Menu

* ListZilla

* Productivity and Networking Information Component (PaNIC)

* Teleflip

* Word Count

If you'd like to put a certain snippet of Javascript on every page, Allow Right-Click or Always Remember Password is the way to go. Alt-Text for Links uses javascript to control tooltips. If you'd like to create your own links menu, then Goon Menu is good to learn from. BugMeNot uses complex regular expressions, while ListZilla deals with setting options and using the extension manager. PaNIC uses user-defined variables in XUL menus, and Teleflip executes third party executable files. Last but not least, WordCount is a good way to learn how to take a bookmarklet and use it as an extension.

The Mozillazine extensions forum is a great place to learn more about creating extensions. They're under heavy loads from time to time, so they might be down when you read this, but try back again if they are, because they have a lot of useful information there.

Loads of other useful extensions can also be found at Mozilla Update, and there's another place called My Extensions Mirror that has forums as well as tons of extensions.

Well, that's it. Hopefully this has been helpful to at least a few ambitious people, as well as a look into what goes into making one for the non-technical types. So get off your ass and make something useful!

Credit to Eric for the guide

Edited by Liger
  • 2 weeks later...
  • 2 weeks later...
Wow amazing guide, it seems really cool! I will definetly try this later.

Do you create real extensions too? And how about one for IE/Maxthon?

Anyway GJ (Y)

585278611[/snapback]

Yes I make extensions but mostly for personal use :) Maybe I will release one.....

I have this one extension that creates a sort of tool bar or icon area where you can choose what it should display for example : you ip address or latest news via xml, email count etc. I havent named it yet :)

  • 2 months later...
  • 3 months later...
  • 6 months later...

*bump*

i have an extension i am making. basically done. but i need the extension have RSS suppot

i am making an extenion that is a dropdown menu. i have it all working and fine. but does anyone know how to get it to use an RSS bookmark?

like a standard live bookmark. i know it can be done. hell, firefoxes ?go? dropdown can have those.

but does anyone know how to define them in an extention? (used as a news update for my site that broadcasts rss)

like when you mouse over it it does the menu to the side thats the firefox RSS showing all the news items

This topic is now closed to further replies.
  • Recently Browsing   0 members

    • No registered users viewing this page.
  • Posts

    • Microsoft Teams is getting a controversial location tracking feature that users may hate by Usama Jawad Image generated with Microsoft Copilot Earlier this year, Microsoft planned to roll out a controversial location tracking feature in Teams, but following customer feedback, it decided to delay its release. The bad news is that the company has decided to launch it later this year, but it's based on roughly the same design that was shared earlier, which means that many users still have good reason to worry. Basically, Microsoft Places and Teams have received workplace check-ins via Wi-Fi. The idea is that if an employee arrives at the office and connects to their enterprise network, their profile status indicator will show them as being present in the office. For example, if you arrive at work, open Teams on your PC, and connect to the "Studio B" company Wi-Fi network, your Teams profile will indicate that you are present in "Studio B", as shown below: Microsoft says that this feature is basically a replacement for physical workplace check-in peripherals, it reduces the need to manually update your status, and it also enables co-workers to know that you're at work so that they can coordinate in-person meetings with you. IT admins can enable this workplace check-in capability at a tenant level, and users have the ability to control whether they want to enable it or not. Of course, all of that sounds great on paper, but naturally, many Teams customers may still have concerns, as they did before. This is because it enables your reporting manager and other members of the organization to track if you are at the office, when you arrive at the office, and where you are right now. This could be problematic for people who work in what they consider to be flexible work environments or hybrid setups, and this kind of location tracking could be considered an invasion of privacy. Microsoft has tried to alleviate some of these concerns by letting users know that they can manually set their location easily, which essentially overrides workplace check-in if they feel uncomfortable with it. However, that doesn't really solve the problem because your organization could enforce a workplace policy that mandates that this feature remains enabled. The Redmond tech giant has also assured users that this capability does not store historical data and is only a real-time indicator of location. Finally, it only generates a signal when you connect to a corporate network, which means that if you are working from home and connect your PC to your personal Wi-Fi, it won't broadcast your location to your employer; you will simply be shown as "Remote". Microsoft has encouraged IT admins to prepare for this change and begin informing users so they know what to expect once it begins rolling out later this year.
    • Wow, Microsoft IS cooking lately... This only shows that they COULD improve, they just chose not to for whatever reasons. That obsession with AI was destroying them from the inside out.
    • BATorrent 4.1.0 by Razvan Serea BATorrent is a lightweight, open-source BitTorrent client built with modern C++ and Qt 6, offering a clean, fast, and privacy-focused alternative to traditional torrent apps. It supports magnet links, .torrent files, resume data, sequential downloading, per-file priorities, and even imports from qBittorrent. Power users benefit from integrated RSS auto-download with regex filtering, duplicate detection, and automatic tracker lists from Stremio. Streaming is seamless thanks to auto-detected players like VLC and IINA. BATorrent includes robust VPN tools—interface binding, auto-detection for WireGuard-based services like Mullvad and NordLynx, kill switch, proxy support, and IP filtering. A full WebUI enables remote control, while integrations with Plex, Jellyfin, and Emby automate library updates. With themes, speed scheduling, system-tray alerts, and cross-platform support for Windows, Linux, and macOS, BATorrent delivers a polished, high-performance torrenting experience. BATorrent features: Core .torrent file and magnet link support Resume data — picks up where you left off after restart Import torrents from qBittorrent Create .torrent files from any file or folder Sequential download mode Per-file priority control (skip, low, normal, high) Seed ratio limits with auto-pause DHT, PEX, UPnP, NAT-PMP RSS Auto-Download Subscribe to RSS feeds — automatically download new torrents as they appear Regex filters — match only what you want (e.g. 1080p|720p, S01E\d+) Per-feed settings — custom save path, check interval (5–1440 min), enable/disable Auto-download — matched items are downloaded automatically in the background Supports magnet links, .torrent URLs, and tags Tray notifications when items are auto-downloaded Duplicate detection — never downloads the same item twice Stremio Stremio Addon System pre-installed — works out of the box Auto tracker list from ngosang/trackerslist Streaming Play while downloading — stream video files before the download is complete Supports mp4, mkv, avi, mov, wmv, flv, webm, m4v, ts Auto-detects installed players (VLC, IINA, system default) VPN & Privacy Interface binding — lock torrent traffic to a specific network interface (e.g. tun0) Auto VPN detection — identifies VPN interfaces (tun, tap, WireGuard, Mullvad, NordLynx, ProtonVPN) Kill switch — automatically pauses all torrents if the VPN interface drops Auto-resume — resumes only the torrents paused by the kill switch when VPN reconnects Proxy support — SOCKS5 and HTTP proxy with optional authentication IP filtering — load P2P blocklists to block unwanted IP ranges Protocol encryption (enabled / forced / disabled) WebUI Remote management — control torrents from any browser at http://localhost:8080 REST API with JSON responses Add torrents via magnet link or .torrent upload Pause, resume, remove torrents remotely View peers and files per torrent Dark theme matching the desktop app HTTP Basic Auth with SHA-256 password hashing Configurable port and remote access (localhost vs 0.0.0.0) Interface 3 themes: Dark, Light, Midnight (bat/vampire aesthetic) Real-time speed graph Detailed panel with tabs: General, Peers, Files, Trackers Filter bar: search by name, filter by state (Active, Downloading, Seeding, Paused, Finished) Drag & drop .torrent files and magnet links Drag & drop reorder in torrent list System tray with notifications (download complete, kill switch events, RSS auto-downloads) Splash screen with bat animation Bilingual: English and Portuguese (BR), auto-detected from system locale Bandwidth Scheduler Alternative speed limits — set different download/upload limits on a schedule Time range — configure active hours (e.g. 01:00 to 07:00), supports overnight ranges Per-day control — choose which days of the week the schedule applies Automatically switches between normal and alternative speeds Media Server Integration Plex — automatically trigger library scan when a download completes Jellyfin / Emby — same automatic library refresh via API Configure server URL and authentication token/key in Settings System Cross-platform: Windows, Linux, macOS Auto-shutdown — automatically shut down PC when all downloads complete (60s cancellable countdown) Auto-update system (AppImage on Linux, installer on Windows, DMG on macOS) CLI arguments: pass .torrent files or magnet: URIs directly Keyboard shortcuts: Space to toggle pause, Ctrl+A to select all, Ctrl+O to open BATorrent 4.1.0 release notes: A community-driven release: everything here came straight from your reports and requests. It closes the remaining gaps with qBittorrent and fixes the Windows settings/tray/splash issues several of you hit. Fixed Settings now actually save. A whole class of preferences — speed limits (and the alternative limits), max active downloads, seed ratio, listen port, max connections, DHT/uTP/encryption, VPN interface, kill switch and proxy — weren't being persisted and reset to defaults on every launch. They now round-trip correctly. (Thanks to everyone who reported "the upload limit always goes back to 0".) Splash and tray toggles stick on Windows. Turning off the startup animation (or "close to tray") no longer reverts — the Windows registry stored these booleans as integers and the UI was misreading them. Close-to-tray hint. The first time the window hides to the tray you get a one-time notification, so the app doesn't look like it vanished (Windows 11 tucks new tray icons into the overflow). macOS Dock icon size. The icon filled its canvas edge-to-edge and rendered larger than neighbouring apps; it now uses the standard safe-area padding. Native file picker language. The "Torrent file / All files" filter in the open dialog follows the app language instead of being hard-coded. Added — qBittorrent parity Alternative speed limits toggle — a turtle button in the toolbar flips your throttled limits on/off instantly, independent of the scheduler. Follow system theme — switch light/dark automatically with the OS (Settings → Appearance). Pre-allocate disk space — reserve the full file size up front to reduce fragmentation (Settings → Downloads). Recheck data on add — optionally force a hash check when adding a torrent, so existing or partial files on disk are detected. Port status indicator — a 🔴 dot in the status bar shows whether your listen port looks reachable (UPnP/NAT-PMP + listen state; fully local, no external check). Add torrent from URL — File → Add torrent from URL (Ctrl+U) fetches a remote .torrent and routes it through the normal add dialog. Export .torrent — right-click a torrent → Export .torrent to save its metadata file. Already there (in case you missed it) Watch folder — auto-add .torrent files dropped into a monitored directory (Settings → Files). This release just surfaces it. Incomplete files already carry a .!bt suffix until they finish. Under the hood Regression tests for the settings-persistence and Windows boolean bugs. A new Qt Quick Test harness covering the startup splash and the design-system widgets. Download: BATorrent 4.1.0 | 37.5 MB (Open Source) Download: BATorrent Portable | 51.7 MB Links: BATorrent Website | Screenshot | Changelog Get alerted to all of our Software updates on Twitter at @NeowinSoftware
  • Recent Achievements

    • Very Popular
      AndrewSteel earned a badge
      Very Popular
    • Veteran
      Taliseian went up a rank
      Veteran
    • One Month Later
      Clizby earned a badge
      One Month Later
    • One Month Later
      Timaximus earned a badge
      One Month Later
    • Week One Done
      Timaximus earned a badge
      Week One Done
  • Popular Contributors

    1. 1
      +primortal
      517
    2. 2
      +Edouard
      163
    3. 3
      PsYcHoKiLLa
      162
    4. 4
      Steven P.
      83
    5. 5
      ATLien_0
      78
  • Tell a friend

    Love Neowin? Tell a friend!