https://github.com/otsobear/chrome2moz
chrome extension to firefox extension converter
https://github.com/otsobear/chrome2moz
chrome chrome-extensions firefox firefox-extensions rust
Last synced: 8 months ago
JSON representation
chrome extension to firefox extension converter
- Host: GitHub
- URL: https://github.com/otsobear/chrome2moz
- Owner: OtsoBear
- Created: 2025-10-06T14:55:43.000Z (9 months ago)
- Default Branch: main
- Last Pushed: 2025-10-08T11:05:45.000Z (9 months ago)
- Last Synced: 2025-10-08T13:11:51.394Z (9 months ago)
- Topics: chrome, chrome-extensions, firefox, firefox-extensions, rust
- Language: Rust
- Homepage:
- Size: 127 KB
- Stars: 2
- Watchers: 0
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
Awesome Lists containing this project
README
# Chrome to Firefox Extension Converter
A powerful Rust-based CLI tool that automatically converts Chrome Manifest V3 extensions to Firefox-compatible format. Handles API conversions, manifest transformations, and generates compatibility shims with support for complex patterns like `executeScript` to message-passing conversion.
## Features
- **Automatic API Conversion**: Converts `chrome.*` namespace to `browser.*`
- **Expanded API Coverage**: 80+ Chrome API mappings including MV3 features
- **Manifest Transformation**: Adapts Chrome MV3 manifests for Firefox compatibility
- **Service Worker Handling**: Converts service workers to Firefox event pages
- **Advanced Transformations**: Automatically converts `executeScript` patterns to message-passing
- **Smart Analysis**: Detects 90+ types of incompatibilities
- **Intelligent Shims**: Auto-generates 10+ compatibility shims based on API usage
- **MV3 API Support**: Handles `storage.session`, `sidePanel`, `userScripts`, and more
- **Legacy API Support**: Maps deprecated Chrome APIs to modern equivalents
- **XPI Packaging**: Creates ready-to-install Firefox extension packages
- **Detailed Reports**: Comprehensive conversion reports with statistics
- **Batch Processing**: Handles multiple files efficiently
## Quick Start
### Installation
```bash
# Clone the repository
git clone https://github.com/OtsoBear/chrome-to-firefox.git
cd chrome-to-firefox
# Build the project
cargo build --release
```
### Your First Conversion
```bash
# Analyze your extension first
cargo run -- analyze -i ./path/to/chrome-extension
# Convert to Firefox format
cargo run -- convert -i ./path/to/chrome-extension -o ./output --report
# Check the results
cat output.md
```
### Try the Example
```bash
# Convert the included test extension
cargo run -- convert -i ./LatexToCalc -o ./converted-output --report
# Expected output:
# Conversion completed successfully!
# Files modified: 5
# Files added: 3 (compatibility shims)
# Total changes: 73
```
## What Gets Converted
### JavaScript Transformations
**API Namespace Conversion:**
```javascript
// Before
chrome.storage.sync.get("key", callback);
chrome.tabs.query({active: true}, callback);
// After
browser.storage.sync.get("key", callback);
browser.tabs.query({active: true}, callback);
```
**Browser Polyfill Injection:**
```javascript
// Added automatically to all JavaScript files
if (typeof browser === 'undefined') {
var browser = chrome;
}
```
**executeScript to Message Passing** (Advanced):
```javascript
// Before (Chrome pattern)
chrome.scripting.executeScript({
target: { tabId: activeTab.id },
function: (reqId) => {
const result = myFunction(reqId); // Function from content script
chrome.runtime.sendMessage({type: "RESULT", result});
},
args: [requestId]
});
// After (Firefox-compatible)
// In background.js:
browser.tabs.sendMessage(activeTab.id, {
type: 'EXECUTE_SCRIPT_REQUEST_265',
args: [requestId]
});
// In content.js (auto-generated listener):
browser.runtime.onMessage.addListener((request, sender, sendResponse) => {
if (request.type === 'EXECUTE_SCRIPT_REQUEST_265') {
const [reqId] = request.args;
const result = myFunction(reqId);
browser.runtime.sendMessage({type: "RESULT", result});
return true;
}
});
```
### Manifest Transformations
**Firefox-Specific Settings:**
```json
{
"browser_specific_settings": {
"gecko": {
"id": "extension@converted.extension",
"strict_min_version": "121.0"
}
}
}
```
**Background Scripts:**
```json
{
"background": {
"service_worker": "background.js",
"scripts": ["background.js"],
"persistent": false
}
}
```
**Permission Restructuring:**
```json
{
"permissions": ["storage", "tabs"],
"host_permissions": ["https://example.com/*"]
}
```
## Usage
### Command Reference
#### Analyze Command
Inspect an extension without converting:
```bash
cargo run -- analyze -i ./extension-directory
```
Output shows:
- All detected incompatibilities
- Severity levels (Blocker, Major, Minor, Info)
- Auto-fixable issues
- Manual action items
#### Convert Command
Convert an extension to Firefox format:
```bash
cargo run -- convert -i ./chrome-extension -o ./firefox-version --report
Options:
-i, --input Input Chrome extension directory
-o, --output Output directory for Firefox version
-r, --report Generate detailed conversion report
```
#### Chrome-Only APIs Command
List WebExtension APIs that currently exist only in Chrome:
```bash
cargo run -- chrome-only-apis
```
This command reaches out to MDN's `browser-compat-data` repository using the GitHub
API (no clone required) and reports every feature where Chrome has support but Firefox
does not. Use it to quickly identify compatibility gaps before starting a port. The
report now highlights how many of the detected APIs already have shims or detection
logic in `src/parser/javascript.rs`, so you can spot remaining work at a glance.
Example summary section:
```text
Summary:
Total Chrome-only APIs found: 42
Implemented (matches parser/javascript.rs): 6
Not yet implemented: 36
Known chrome-only prefixes tracked: 14
Known prefixes missing from MDN dataset: 2
Missing prefixes:
- chrome.downloads.acceptDanger
- chrome.downloads.setShelfEnabled
```
### Output Structure
After conversion:
```
output/
├── manifest.json # Transformed for Firefox
├── background.js # chrome.* → browser.*
├── content.js # With auto-generated listeners
├── popup.js # Converted
└── [other extension files]
output.xpi # Ready-to-install Firefox package
output.md # Detailed conversion report
```
### Conversion Report
The report includes:
```markdown
## Summary
- Extension: LatexToCalc v2.0.1
- Conversion Status: ✅ Success
- Files Modified: 5
- Total Changes: 73
- Chrome API Calls Converted: 57
- Callback→Promise Conversions: 10
## Transformations
- background.js: 36 changes
- ✓ Converted chrome → browser (8)
- ✓ Converted executeScript to message passing (3)
- ✓ Added browser polyfill
```
## Testing in Firefox
### Method 1: Temporary Add-on
1. Open Firefox
2. Go to `about:debugging#/runtime/this-firefox`
3. Click "Load Temporary Add-on"
4. Select `output/manifest.json`
### Method 2: Install XPI
1. Open Firefox
2. Go to `about:addons`
3. Click gear icon → "Install Add-on From File"
4. Select `output.xpi`
### Debugging
Check the Browser Console (Ctrl+Shift+J) for any errors.
## Key Transformations
### 1. Chrome API → Browser API
- All `chrome.*` calls converted to `browser.*`
- Maintains backward compatibility with Chrome
### 2. Manifest V3 → Firefox MV3
- Adds `browser_specific_settings.gecko.id`
- Converts service workers to event pages
- Restructures permissions
### 3. executeScript Isolation Handling
- Detects `scripting.executeScript` with function references
- Extracts function code and variables
- Generates message passing architecture
- Creates listeners in content scripts
### 4. declarativeNetRequest → webRequest Conversion
Chrome's declarative network request API is automatically converted to Firefox's imperative webRequest:
```javascript
// Chrome DNR rule (declarative)
chrome.declarativeNetRequest.updateDynamicRules({
addRules: [{
id: 1,
priority: 1,
action: { type: 'block' },
condition: {
urlFilter: '||ads.example.com/*',
resourceTypes: ['script', 'image']
}
}]
});
// Converted to Firefox webRequest (imperative)
browser.webRequest.onBeforeRequest.addListener(
(details) => {
if (matchesCondition(details)) {
return { cancel: true };
}
},
{ urls: ['*://ads.example.com/*'], types: ['script', 'image'] },
['blocking']
);
```
**Supported DNR Actions:**
- **Block**: Converts to `onBeforeRequest` with `{cancel: true}`
- **Redirect**: Converts to `onBeforeRequest` with `{redirectUrl: newUrl}`
- Supports URL rewrites, regex substitution, URL transformations
- **ModifyHeaders**: Converts to `onBeforeSendHeaders`/`onHeadersReceived`
- Supports request and response header modifications
- **UpgradeScheme**: HTTP→HTTPS via redirect
**Rule Features:**
- Domain and initiator filtering
- Resource type filtering
- URL pattern conversion
- Dynamic and session rule support
- Debug events emulation
### 5. Compatibility Shims
Generated shims provide extensive cross-browser support:
**Core Shims:**
- `browser-polyfill.js`: Namespace compatibility
- `action-compat.js`: Action API bridging
- `promise-wrapper.js`: Callback-to-promise helpers
**MV3 API Shims:**
- `storage-session-compat.js`: Native in Firefox 115+, in-memory polyfill for older versions
- `sidepanel-compat.js`: Maps `sidePanel` to Firefox's `sidebarAction`
- `declarative-net-request-stub.js`: Converts DNR rules to `webRequest` listeners automatically
- `user-scripts-compat.js`: Translates `userScripts` API
**Legacy API Shims:**
- `tabs-windows-compat.js`: Maps deprecated `tabs.getSelected`, `tabs.getAllInWindow`
- `runtime-compat.js`: Stubs `runtime.getPackageDirectoryEntry`
**Optional Shims:**
- `downloads-compat.js`: Handles Chrome-specific download features
- `privacy-stub.js`: Stubs `chrome.privacy` API
- `notifications-compat.js`: Adapts notification options for Firefox
## ⚠️ Known Limitations
### Chrome-Only APIs
Some Chrome features have no or limited Firefox equivalent:
**Not Available (Blockers):**
- `chrome.offscreen.*` - No equivalent
- `chrome.declarativeContent.*` - No equivalent
- `chrome.tabGroups.*` - No equivalent
**Partial Support (Shims Provided):**
- `chrome.sidePanel.*` - Maps to Firefox's `sidebarAction` (different UI)
- `chrome.declarativeNetRequest.*` - Automatically converted to `webRequest` listeners at runtime
- Supports: block, redirect, modifyHeaders, upgradeScheme rules
- Converts dynamic/session rules to imperative callbacks
- Note: Static rulesets and allow rules have limited support
- `chrome.userScripts.*` - Maps to Firefox's different API structure
- `chrome.storage.session` - In-memory polyfill (data not persisted)
- `chrome.privacy.*` - Stubbed as read-only (use Firefox preferences)
**Legacy APIs (Shims Provided):**
- `tabs.getSelected` / `tabs.getAllInWindow` - Mapped to modern `tabs.query`
- `runtime.getPackageDirectoryEntry` - Stubbed with guidance
The tool automatically applies shims where possible and flags blockers in the report.
### Service Workers vs Event Pages
Chrome uses service workers, Firefox uses event pages:
- Different lifecycle management
- No `importScripts()` in Firefox
- Converted to `background.scripts` array
### Host Permissions
Firefox treats `host_permissions` as optional (user can deny), while Chrome grants them at install time.
## Development
### Building
```bash
# Debug build
cargo build
# Release build (optimized)
cargo build --release
# Run tests
cargo test
# Code quality
cargo fmt
cargo clippy
```
### Project Structure
```
src/
├── main.rs # CLI entry point
├── lib.rs # Library root
├── models/ # Data structures
├── parser/ # Manifest & JS parsing
├── analyzer/ # Incompatibility detection
├── transformer/ # Code transformation
│ ├── manifest.rs # Manifest transformer
│ └── javascript.rs # JS transformer (executeScript conversion)
├── packager/ # XPI packaging
├── validator/ # Output validation
└── report/ # Report generation
```
### Running with Cargo
```bash
# Analyze
cargo run -- analyze -i ./LatexToCalc
# Convert
cargo run -- convert -i ./LatexToCalc -o ./output --report
# Use release build (faster)
./target/release/chrome-to-firefox convert -i ./extension -o ./output
```
## Documentation
- **[ARCHITECTURE.md](ARCHITECTURE.md)** - Technical architecture and implementation details
- **Conversion Reports** - Generated with `--report` flag
- **In-code Documentation** - Run `cargo doc --open`
## Contributing
Contributions are welcome! Areas for contribution:
- Additional API mappings
- More test cases
- Documentation improvements
- Bug fixes
- New features
See the LatexToCalc extension as a reference for testing.
## Troubleshooting
### Build Errors
```bash
cargo clean
cargo build --release
```
### Conversion Issues
1. Check the error message
2. Review the conversion report
3. Ensure input is valid Chrome MV3
4. Check file permissions
### Extension Doesn't Work
1. Open Browser Console (Ctrl+Shift+J)
2. Check for JavaScript errors
3. Review manifest in `about:debugging`
4. Check permissions are granted
## License
This project is licensed under the MIT License.
## Acknowledgments
- Built with Rust
- Test extension: [LatexToCalc](LatexToCalc/)
- Inspired by the need for cross-browser extension compatibility
## Support
- [Report a bug](https://github.com/OtsoBear/chrome-to-firefox/issues)
- [Request a feature](https://github.com/OtsoBear/chrome-to-firefox/issues)
- [Read the architecture docs](./ARCHITECTURE.md)
---
**Status**: Production-ready
**Version**: 0.1.0
**Last Updated**: October 2025
Made with care for the open web