Native Messaging Helper for WebExtensions
Rust helpers for building native messaging hosts for WebExtensions, with a config-driven installer and correct-by-default protocol handling.
This crate handles:
-
Writing browser-correct native messaging manifests
- Chromium family →
allowed_origins - Firefox family →
allowed_extensions
- Chromium family →
-
Installing manifests at user or system scope
-
Windows registry handling (for Chromium and Firefox-family browsers)
-
Verifying and removing installations
-
Correct message framing (4-byte length prefix + UTF-8 JSON)
-
Async helpers for reading, writing, and running a host loop
Build the host logic that matters — leave manifests, paths, and wire protocol details to this crate.
Goals of this crate
Make the native host side of WebExtensions native messaging:
- Boringly correct
- Portable across browsers and OSes
- Easy to test and reason about
Design principles
-
Config-driven browser support Browsers are defined in an embedded
browsers.toml. Adding support for new browsers (Brave, Vivaldi, LibreWolf, etc.) does not require code changes — only config. -
Correct manifests by construction The installer always emits the right JSON shape per browser family.
-
Registry-aware on Windows Verification and removal correctly handle registry-only installs.
-
Async-first host helpers Minimal, focused helpers to ship a production host quickly.
What this library is (and isn’t)
✅ This crate is for:
- The native host application
- Writing / installing / verifying native messaging manifests
- Framing and exchanging JSON messages with the browser
❌ This crate is not:
- A browser extension SDK
- A replacement for
chrome.runtime.connectNative/browser.runtime.connectNative
You still write standard extension code — this crate handles the native side.
Features
-
✅ Cross-browser Chrome, Edge, Chromium, Brave, Vivaldi, Firefox, LibreWolf (via config)
-
✅ Cross-platform Linux, macOS, Windows
-
✅ Registry-aware verification on Windows
-
✅ User & system scope installs
-
✅ Correct native messaging protocol helpers
Supported platforms
| OS | Chromium family | Firefox family | Notes |
|---|---|---|---|
| Linux | ✅ | ✅ | Absolute path required |
| macOS | ✅ | ✅ | Absolute path required |
| Windows | ✅ | ✅ | Registry keys used for discovery |
Install
[]
= "0.1.3"
= { = "1", = ["derive"] }
= { = "1", = ["full"] }
Quick Start
Install manifests (config-driven browsers)
Browsers are selected using string keys from the embedded browsers.toml
(e.g. "chrome", "firefox", "edge", "brave", "vivaldi").
use Path;
use ;
Verify installation
Verification is registry-aware on Windows and filesystem-based on Unix.
use ;
Remove manifests
use ;
Send / receive messages
Native messaging uses length-prefixed UTF-8 JSON.
Read one message
use get_message;
async
Send one message
use send_message;
use Serialize;
async
Run an async event loop
use ;
use json;
use io;
async
API Overview
install
install(...)verify_installed(...)remove(...)Scope::{User, System}
The installer is config-driven. Browser behavior comes from browsers.toml, not Rust enums.
host
encode_messagedecode_messageget_messagesend_messageevent_loop
Protocol rules enforced:
- 4-byte length prefix
- UTF-8 JSON
- 1 MB host → browser limit
- configurable browser → host limit
Extension-side notes
Chromium family
- Uses
allowed_origins - Requires
"permissions": ["nativeMessaging"] - Call
chrome.runtime.connectNative("com.example.native_host")
Firefox family
- Uses
allowed_extensions - Requires a stable add-on ID:
- Call
browser.runtime.connectNative("com.example.native_host")
Testing locally
-
Unit tests validate:
- framing correctness
- manifest JSON shape
- path resolution
- install/remove/verify behavior
-
Windows registry logic is exercised on Windows CI
-
No real browser required for tests
Troubleshooting
Host not found
- Name mismatch between extension & manifest
- Wrong scope (User vs System)
- Windows: registry key missing
- Non-absolute path on macOS/Linux
Disconnects
- Host crashed (run manually for stderr)
- Message size exceeded
- MV3 service worker reconnect needed
Contributing
PRs welcome. Please keep changes:
- Config-driven
- Cross-platform
- Well-tested
License
MIT
Build great WebExtensions — this crate handles the native side, correctly.