@@ -62,7 +62,7 @@ This installs the host to `~/.bridgeswarm/` (or `%LOCALAPPDATA%\bridgeswarm\` on
|
||||
1. Open `chrome://extensions`
|
||||
2. Enable **Developer mode**
|
||||
3. Drag & drop `~/Downloads/BridgeSwarm-1.0.0.zip` onto the page (or Load unpacked after extracting)
|
||||
4. Extension ID should be `fmcenppcipeikpnpopolicnllljclmmi`
|
||||
4. Extension ID should be `jhmbaojjfkkpoolhkoohklbjokdmbdpm`
|
||||
5. Restart the browser
|
||||
|
||||
**Firefox:** temporary via `about:debugging` → Load Temporary Add-on, or permanent on Nightly/Dev Edition via Install Add-on From File (`.xpi`).
|
||||
|
||||
@@ -4,9 +4,9 @@
|
||||
"path": "ABSOLUTE_PATH_TO_NATIVE_HOST",
|
||||
"type": "stdio",
|
||||
"allowed_origins": [
|
||||
"chrome-extension://fmcenppcipeikpnpopolicnllljclmmi/"
|
||||
"chrome-extension://jhmbaojjfkkpoolhkoohklbjokdmbdpm/"
|
||||
],
|
||||
"allowed_extensions": [
|
||||
"bridgeswarm-58514e5bbfe0d5e3@example.org"
|
||||
"bridgeswarm-2b4c4bed6fceb6de@example.org"
|
||||
]
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
"name": "BridgeSwarm",
|
||||
"version": "1.0.0",
|
||||
"description": "P2P Hyperswarm in the browser via native messaging host",
|
||||
"key": "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAmpSyoCuwrSnyspandk7hcQ3rTVegPWPyABcn9qX9EMleN7FIPRN81Z31IPXnbMDfXavnAnUc0vEH1ujtv/PAjew58kN4CFUTE1opU15v6dzn+ltrtG1aX+9dwYAOBsxKFU5TzfXI4SvixWzEGjJ1Irh4QEYJh4/C1A8mOdF+VvIA4y5ko7npH+7SRmCnxQ+c4Jh7gmG7qvblEHZzvM5VxT0H4gXivxD7+ABDQFnlet8ojVgyN6azND4BuPER5672vRdzjr4Emd9bL1L3N9QzQzvT7tUdFkJ2Giph9Bog9yyymnxbb8S4u0u8OlDdLBQlCWrERoYxHG9QGZse1EFWsQIDAQAB",
|
||||
"key": "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxbk6DH/lfwyITfu7q07GIvt29Ee1IubQpVCK6Njw+WTs3jDJkcBh6VIfRsTzc1cg8W7M5IUST8B6yyKHVk41/ydVzeNCVJCxHnUr6PZAAEkTq6+moi6z++eUumhN3nY+T8FC57clG7ffhTfeZ7kwDXQLyQkDf6uoZeJL4MQ49R8aILlrTeGSCdCbwY3JzZSRgtHj1RGLHjs+J6wMIou+RtzTEEmCbyXkyywQ8UbKDzIqOVQx1TIWAWwp/FSZtcmWmjR1Ipnp9TxaGhiS6fVLnxT3aGDqLXilKoPoKPNUVb5B0NTgzzMKmqJ1yRlw8knZ5lDoYJ5p4Rj1wR1cjyskOwIDAQAB",
|
||||
"permissions": [
|
||||
"nativeMessaging",
|
||||
"storage",
|
||||
@@ -50,7 +50,7 @@
|
||||
},
|
||||
"browser_specific_settings": {
|
||||
"gecko": {
|
||||
"id": "bridgeswarm-58514e5bbfe0d5e3@example.org",
|
||||
"id": "bridgeswarm-2b4c4bed6fceb6de@example.org",
|
||||
"strict_min_version": "79.0"
|
||||
}
|
||||
},
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
{
|
||||
"manifest_version": 3,
|
||||
"name": "BridgeSwarm",
|
||||
"version": "1.0.0",
|
||||
"description": "P2P Hyperswarm in the browser via native messaging host",
|
||||
"permissions": [
|
||||
"nativeMessaging",
|
||||
"storage",
|
||||
"scripting",
|
||||
"notifications",
|
||||
"tabs"
|
||||
],
|
||||
"action": {
|
||||
"default_title": "BridgeSwarm Dashboard"
|
||||
},
|
||||
"background": {
|
||||
"service_worker": "background.js"
|
||||
},
|
||||
"content_scripts": [
|
||||
{
|
||||
"matches": [
|
||||
"<all_urls>"
|
||||
],
|
||||
"js": [
|
||||
"content.js"
|
||||
],
|
||||
"run_at": "document_start"
|
||||
}
|
||||
],
|
||||
"web_accessible_resources": [
|
||||
{
|
||||
"resources": [
|
||||
"api.js",
|
||||
"framed-stream.js",
|
||||
"protomux-bundle.js",
|
||||
"defaults.js",
|
||||
"dashboard.html",
|
||||
"dashboard.js"
|
||||
],
|
||||
"matches": [
|
||||
"<all_urls>"
|
||||
]
|
||||
}
|
||||
],
|
||||
"icons": {
|
||||
"16": "icons/16.png",
|
||||
"48": "icons/48.png",
|
||||
"128": "icons/128.png"
|
||||
},
|
||||
"browser_specific_settings": {
|
||||
"gecko": {
|
||||
"id": "[email protected]",
|
||||
"strict_min_version": "79.0"
|
||||
}
|
||||
},
|
||||
"options_ui": {
|
||||
"page": "options.html"
|
||||
}
|
||||
}
|
||||
@@ -5,6 +5,7 @@
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"setup": "node scripts/run-install.js",
|
||||
"generate:extension-id": "node scripts/generate-extension-id.js",
|
||||
"build:host": "node scripts/build-host.js",
|
||||
"build:protomux": "node scripts/bundle-protomux.js",
|
||||
"build:hrpc": "node scripts/build-hrpc.js",
|
||||
|
||||
Regular → Executable
+27
-12
@@ -1,8 +1,13 @@
|
||||
#!/usr/bin/env node
|
||||
'use strict';
|
||||
/**
|
||||
* Generates a new extension ID and updates manifest.json and com.bridgeswarm.json.
|
||||
* Run on install so each copy of the template gets a unique ID (no overwrites).
|
||||
* Generates a new BridgeSwarm extension ID pair and updates:
|
||||
* - extension/manifest.json (Chrome key + gecko id)
|
||||
* - extension/manifest_firefox.json (gecko id only; no key)
|
||||
* - com.bridgeswarm.json (allowed_origins / allowed_extensions)
|
||||
*
|
||||
* Also prints the IDs so installers/docs can be synced.
|
||||
* Do NOT reuse holesail-browser's Chrome key/ID — they must stay unique.
|
||||
*/
|
||||
const crypto = require('crypto');
|
||||
const fs = require('fs');
|
||||
@@ -10,29 +15,24 @@ const path = require('path');
|
||||
|
||||
const repoRoot = path.join(__dirname, '..');
|
||||
const manifestPath = path.join(repoRoot, 'extension', 'manifest.json');
|
||||
const manifestFirefoxPath = path.join(repoRoot, 'extension', 'manifest_firefox.json');
|
||||
const nativeManifestPath = path.join(repoRoot, 'com.bridgeswarm.json');
|
||||
|
||||
// Generate RSA 2048-bit key pair
|
||||
const { publicKey } = crypto.generateKeyPairSync('rsa', {
|
||||
modulusLength: 2048,
|
||||
publicKeyEncoding: { type: 'spki', format: 'der' },
|
||||
privateKeyEncoding: { type: 'pkcs8', format: 'der' }
|
||||
privateKeyEncoding: { type: 'pkcs8', format: 'der' },
|
||||
});
|
||||
|
||||
// Chrome extension ID: first 16 bytes of SHA256(publicKey), each byte -> 2 chars a-p
|
||||
// (Chromium crx_id.py: HexToMPDecimal)
|
||||
// Chrome extension ID: first 16 bytes of SHA256(publicKey), each nibble → a–p
|
||||
const hash = crypto.createHash('sha256').update(publicKey).digest();
|
||||
const chromeId = Array.from(hash.slice(0, 16))
|
||||
.map(b => String.fromCharCode(97 + (b >> 4)) + String.fromCharCode(97 + (b & 0x0f)))
|
||||
.map((b) => String.fromCharCode(97 + (b >> 4)) + String.fromCharCode(97 + (b & 0x0f)))
|
||||
.join('');
|
||||
|
||||
// Firefox ID: unique per install
|
||||
const firefoxId = 'bridgeswarm-' + crypto.randomBytes(8).toString('hex') + '@example.org';
|
||||
|
||||
// Base64-encode public key for manifest
|
||||
const keyBase64 = publicKey.toString('base64');
|
||||
|
||||
// Update extension manifest
|
||||
const manifest = JSON.parse(fs.readFileSync(manifestPath, 'utf8'));
|
||||
manifest.key = keyBase64;
|
||||
if (manifest.browser_specific_settings?.gecko) {
|
||||
@@ -40,10 +40,25 @@ if (manifest.browser_specific_settings?.gecko) {
|
||||
}
|
||||
fs.writeFileSync(manifestPath, JSON.stringify(manifest, null, 2) + '\n');
|
||||
|
||||
// Update native host manifest template
|
||||
// Firefox manifest: same as Chrome but without the Chrome-only "key"
|
||||
if (fs.existsSync(manifestFirefoxPath)) {
|
||||
const manifestFx = JSON.parse(fs.readFileSync(manifestFirefoxPath, 'utf8'));
|
||||
if (manifestFx.browser_specific_settings?.gecko) {
|
||||
manifestFx.browser_specific_settings.gecko.id = firefoxId;
|
||||
}
|
||||
delete manifestFx.key;
|
||||
fs.writeFileSync(manifestFirefoxPath, JSON.stringify(manifestFx, null, 2) + '\n');
|
||||
} else {
|
||||
const fx = { ...manifest };
|
||||
delete fx.key;
|
||||
fs.writeFileSync(manifestFirefoxPath, JSON.stringify(fx, null, 2) + '\n');
|
||||
}
|
||||
|
||||
const nativeManifest = JSON.parse(fs.readFileSync(nativeManifestPath, 'utf8'));
|
||||
nativeManifest.allowed_origins = ['chrome-extension://' + chromeId + '/'];
|
||||
nativeManifest.allowed_extensions = [firefoxId];
|
||||
fs.writeFileSync(nativeManifestPath, JSON.stringify(nativeManifest, null, 2) + '\n');
|
||||
|
||||
console.log('Generated extension ID:', chromeId, '(' + firefoxId + ')');
|
||||
console.log('CHROME_EXT_ID=' + chromeId);
|
||||
console.log('FIREFOX_EXT_ID=' + firefoxId);
|
||||
|
||||
+4
-2
@@ -10,8 +10,10 @@ $InstallDir = "$env:LOCALAPPDATA\bridgeswarm"
|
||||
$Downloads = "$env:USERPROFILE\Downloads"
|
||||
$ManifestName = "com.bridgeswarm"
|
||||
$ExtVersion = "1.0.0"
|
||||
$ChromeExtId = "fmcenppcipeikpnpopolicnllljclmmi"
|
||||
$FirefoxExtId = "bridgeswarm[email protected]"
|
||||
# Must match extension/manifest.json "key" / gecko.id and com.bridgeswarm.json
|
||||
# (unique to BridgeSwarm — do not share with holesail-browser)
|
||||
$ChromeExtId = "jhmbaojjfkkpoolhkoohklbjokdmbdpm"
|
||||
$FirefoxExtId = "[email protected]"
|
||||
|
||||
$HostZip = "bridge-swarm-host-win32-x64.zip"
|
||||
$ExtZip = "BridgeSwarm-$ExtVersion.zip"
|
||||
|
||||
+4
-2
@@ -13,8 +13,10 @@ INSTALL_DIR="$HOME/.bridgeswarm"
|
||||
MANIFEST_NAME="com.bridgeswarm"
|
||||
DOWNLOADS="$HOME/Downloads"
|
||||
EXT_VERSION="1.0.0"
|
||||
CHROME_EXT_ID="fmcenppcipeikpnpopolicnllljclmmi"
|
||||
FIREFOX_EXT_ID="bridgeswarm[email protected]"
|
||||
# Must match extension/manifest.json "key" / gecko.id and com.bridgeswarm.json
|
||||
# (unique to BridgeSwarm — do not share with holesail-browser)
|
||||
CHROME_EXT_ID="jhmbaojjfkkpoolhkoohklbjokdmbdpm"
|
||||
FIREFOX_EXT_ID="[email protected]"
|
||||
|
||||
# ── Detect platform ────────────────────────────────────────────────────────────
|
||||
OS="$(uname -s | tr '[:upper:]' '[:lower:]')"
|
||||
|
||||
+39
-12
@@ -1,7 +1,8 @@
|
||||
/**
|
||||
* Pack the browser extension into a zip (and .xpi) for distribution.
|
||||
* Pack the browser extension into a zip (Chrome) and .xpi (Firefox).
|
||||
* Zip contains manifest.json (Chrome, with "key").
|
||||
* XPI contains manifest_firefox.json as manifest.json (no "key").
|
||||
* Output: releases/BridgeSwarm-<version>.zip, releases/BridgeSwarm-<version>.xpi
|
||||
* Excludes: protomux-entry.cjs, *.map
|
||||
*/
|
||||
|
||||
const fs = require('fs');
|
||||
@@ -13,10 +14,8 @@ const REPO_ROOT = path.resolve(__dirname, '..');
|
||||
const EXT_DIR = path.join(REPO_ROOT, 'extension');
|
||||
const RELEASES_DIR = path.join(REPO_ROOT, 'releases');
|
||||
|
||||
const EXCLUDE = new Set([
|
||||
'protomux-entry.cjs',
|
||||
'.map'
|
||||
]);
|
||||
const EXCLUDE_NAMES = new Set(['protomux-entry.cjs']);
|
||||
const EXCLUDE_EXTS = new Set(['.map']);
|
||||
|
||||
function getVersion() {
|
||||
const manifestPath = path.join(EXT_DIR, 'manifest.json');
|
||||
@@ -34,8 +33,9 @@ function listExtensionFiles(dir, base = dir) {
|
||||
if (e.isDirectory()) {
|
||||
files.push(...listExtensionFiles(full, base));
|
||||
} else {
|
||||
const skip = EXCLUDE.has(e.name) || [...EXCLUDE].some(x => x.startsWith('.') && rel.endsWith(x));
|
||||
if (!skip) files.push({ full, rel });
|
||||
const ext = path.extname(e.name);
|
||||
if (EXCLUDE_NAMES.has(e.name) || EXCLUDE_EXTS.has(ext)) continue;
|
||||
files.push({ full, rel });
|
||||
}
|
||||
}
|
||||
return files;
|
||||
@@ -51,7 +51,7 @@ function createZip(version) {
|
||||
archive.on('error', reject);
|
||||
archive.pipe(output);
|
||||
|
||||
const files = listExtensionFiles(EXT_DIR);
|
||||
const files = listExtensionFiles(EXT_DIR).filter(({ rel }) => rel !== 'manifest_firefox.json');
|
||||
for (const { full, rel } of files) {
|
||||
archive.file(full, { name: rel });
|
||||
}
|
||||
@@ -59,6 +59,32 @@ function createZip(version) {
|
||||
});
|
||||
}
|
||||
|
||||
function createXpi(version) {
|
||||
const firefoxManifestPath = path.join(EXT_DIR, 'manifest_firefox.json');
|
||||
if (!fs.existsSync(firefoxManifestPath)) {
|
||||
throw new Error('extension/manifest_firefox.json missing — run scripts/generate-extension-id.js');
|
||||
}
|
||||
|
||||
const xpiPath = path.join(RELEASES_DIR, `BridgeSwarm-${version}.xpi`);
|
||||
const output = fs.createWriteStream(xpiPath);
|
||||
const archive = archiver('zip', { zlib: { level: 9 } });
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
output.on('close', () => resolve(xpiPath));
|
||||
archive.on('error', reject);
|
||||
archive.pipe(output);
|
||||
|
||||
const files = listExtensionFiles(EXT_DIR).filter(
|
||||
({ rel }) => rel !== 'manifest.json' && rel !== 'manifest_firefox.json'
|
||||
);
|
||||
for (const { full, rel } of files) {
|
||||
archive.file(full, { name: rel });
|
||||
}
|
||||
archive.file(firefoxManifestPath, { name: 'manifest.json' });
|
||||
archive.finalize();
|
||||
});
|
||||
}
|
||||
|
||||
async function main() {
|
||||
const version = getVersion();
|
||||
console.log('BridgeSwarm version from manifest:', version);
|
||||
@@ -71,12 +97,13 @@ async function main() {
|
||||
console.log('Created releases/');
|
||||
}
|
||||
|
||||
console.log('Creating zip...');
|
||||
try {
|
||||
console.log('Creating Chrome zip...');
|
||||
const zipPath = await createZip(version);
|
||||
console.log('Written:', zipPath);
|
||||
const xpiPath = path.join(RELEASES_DIR, `BridgeSwarm-${version}.xpi`);
|
||||
fs.copyFileSync(zipPath, xpiPath);
|
||||
|
||||
console.log('Creating Firefox xpi...');
|
||||
const xpiPath = await createXpi(version);
|
||||
console.log('Written:', xpiPath);
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
|
||||
@@ -1,11 +1,43 @@
|
||||
# Update native host manifest with your Chrome extension ID (fix "Access forbidden").
|
||||
# Usage: .\scripts\update-native-manifest-extension-id.ps1 YOUR_EXTENSION_ID
|
||||
param([Parameter(Mandatory=$true)] [string] $ExtensionId)
|
||||
# Optionally pass a Firefox extension ID as the second argument.
|
||||
# Usage:
|
||||
# .\scripts\update-native-manifest-extension-id.ps1 CHROME_EXT_ID
|
||||
# .\scripts\update-native-manifest-extension-id.ps1 CHROME_EXT_ID FIREFOX_EXT_ID
|
||||
param(
|
||||
[Parameter(Mandatory = $true)][string]$ExtensionId,
|
||||
[Parameter(Mandatory = $false)][string]$FirefoxExtensionId
|
||||
)
|
||||
|
||||
$ExtensionId = $ExtensionId -replace '^chrome-extension://', '' -replace '/$', ''
|
||||
$Origin = "chrome-extension://$ExtensionId/"
|
||||
$manifestFile = (Get-ItemProperty -Path "HKCU:\Software\Google\Chrome\NativeMessagingHosts\com.bridgeswarm" -ErrorAction SilentlyContinue).'(Default)'
|
||||
if (-not $manifestFile -or -not (Test-Path $manifestFile)) { Write-Host "Run scripts/install.ps1 first."; exit 1 }
|
||||
$m = Get-Content $manifestFile -Raw | ConvertFrom-Json
|
||||
$m.allowed_origins = @($Origin)
|
||||
$m | ConvertTo-Json -Depth 4 | Set-Content $manifestFile -Encoding UTF8
|
||||
Write-Host "Updated $manifestFile. Restart Chrome."
|
||||
$updated = $false
|
||||
|
||||
$chromeKey = "HKCU:\Software\Google\Chrome\NativeMessagingHosts\com.bridgeswarm"
|
||||
$manifestFile = (Get-ItemProperty -Path $chromeKey -ErrorAction SilentlyContinue).'(Default)'
|
||||
if ($manifestFile -and (Test-Path $manifestFile)) {
|
||||
$m = Get-Content $manifestFile -Raw | ConvertFrom-Json
|
||||
$m.allowed_origins = @($Origin)
|
||||
$m | ConvertTo-Json -Depth 4 | Set-Content $manifestFile -Encoding UTF8
|
||||
Write-Host "Updated $manifestFile (allowed_origins)"
|
||||
$updated = $true
|
||||
}
|
||||
|
||||
if ($FirefoxExtensionId) {
|
||||
$ffKey = "HKCU:\Software\Mozilla\NativeMessagingHosts\com.bridgeswarm"
|
||||
$ffManifest = (Get-ItemProperty -Path $ffKey -ErrorAction SilentlyContinue).'(Default)'
|
||||
if ($ffManifest -and (Test-Path $ffManifest)) {
|
||||
$m = Get-Content $ffManifest -Raw | ConvertFrom-Json
|
||||
$m.allowed_extensions = @($FirefoxExtensionId)
|
||||
$m | ConvertTo-Json -Depth 4 | Set-Content $ffManifest -Encoding UTF8
|
||||
Write-Host "Updated $ffManifest (allowed_extensions)"
|
||||
$updated = $true
|
||||
} else {
|
||||
Write-Host "Note: Firefox manifest not found — skipping Firefox update"
|
||||
}
|
||||
}
|
||||
|
||||
if (-not $updated) {
|
||||
Write-Host "No manifest found. Run scripts/install.ps1 first."
|
||||
exit 1
|
||||
}
|
||||
Write-Host "Done. Restart your browser."
|
||||
|
||||
@@ -1,15 +1,27 @@
|
||||
#!/usr/bin/env bash
|
||||
# Update native host manifest with your Chrome extension ID (fix "Access forbidden").
|
||||
# Usage: ./scripts/update-native-manifest-extension-id.sh YOUR_EXTENSION_ID
|
||||
# Also accepts a Firefox extension ID as a second argument to update allowed_extensions.
|
||||
# Usage: ./scripts/update-native-manifest-extension-id.sh CHROME_EXT_ID [FIREFOX_EXT_ID]
|
||||
set -e
|
||||
[[ -z "$1" ]] && echo "Usage: $0 YOUR_CHROME_EXTENSION_ID (from chrome://extensions)" && exit 1
|
||||
[[ -z "$1" ]] && echo "Usage: $0 CHROME_EXT_ID [FIREFOX_EXT_ID]" && exit 1
|
||||
EXT_ID="${1#chrome-extension://}"; EXT_ID="${EXT_ID%/}"
|
||||
ORIGIN="chrome-extension://${EXT_ID}/"
|
||||
CHROME_DIR="$HOME/.config/google-chrome/NativeMessagingHosts"
|
||||
CHROMIUM_DIR="$HOME/.config/chromium/NativeMessagingHosts"
|
||||
[[ "$OSTYPE" == "darwin"* ]] && CHROME_DIR="$HOME/Library/Application Support/Google/Chrome/NativeMessagingHosts" && CHROMIUM_DIR="$HOME/Library/Application Support/Chromium/NativeMessagingHosts"
|
||||
FIREFOX_EXT_ID="${2:-}"
|
||||
|
||||
MANIFEST_NAME="com.bridgeswarm"
|
||||
|
||||
if [[ "$OSTYPE" == "darwin"* ]]; then
|
||||
CHROME_DIR="$HOME/Library/Application Support/Google/Chrome/NativeMessagingHosts"
|
||||
CHROMIUM_DIR="$HOME/Library/Application Support/Chromium/NativeMessagingHosts"
|
||||
FIREFOX_DIR="$HOME/Library/Application Support/Mozilla/NativeMessagingHosts"
|
||||
else
|
||||
CHROME_DIR="$HOME/.config/google-chrome/NativeMessagingHosts"
|
||||
CHROMIUM_DIR="$HOME/.config/chromium/NativeMessagingHosts"
|
||||
FIREFOX_DIR="$HOME/.mozilla/native-messaging-hosts"
|
||||
fi
|
||||
|
||||
updated=0
|
||||
|
||||
for dir in "$CHROME_DIR" "$CHROMIUM_DIR"; do
|
||||
f="$dir/${MANIFEST_NAME}.json"
|
||||
[[ ! -f "$f" ]] && continue
|
||||
@@ -18,8 +30,24 @@ for dir in "$CHROME_DIR" "$CHROMIUM_DIR"; do
|
||||
else
|
||||
sed -i.bak "s|\"chrome-extension://[^\"]*/\"|\"$ORIGIN\"|g" "$f" && rm -f "${f}.bak"
|
||||
fi
|
||||
echo "Updated $f"
|
||||
echo "Updated $f (allowed_origins)"
|
||||
updated=1
|
||||
done
|
||||
|
||||
if [[ -n "$FIREFOX_EXT_ID" ]]; then
|
||||
f="$FIREFOX_DIR/${MANIFEST_NAME}.json"
|
||||
if [[ -f "$f" ]]; then
|
||||
if command -v node >/dev/null 2>&1; then
|
||||
node -e "const fs=require('fs');const j=JSON.parse(fs.readFileSync('$f','utf8'));j.allowed_extensions=['$FIREFOX_EXT_ID'];fs.writeFileSync('$f',JSON.stringify(j,null,2));"
|
||||
else
|
||||
sed -i.bak "s|\"bridgeswarm[^\"]*@[^\"]*\"|\"$FIREFOX_EXT_ID\"|g" "$f" && rm -f "${f}.bak"
|
||||
fi
|
||||
echo "Updated $f (allowed_extensions)"
|
||||
updated=1
|
||||
else
|
||||
echo "Note: Firefox manifest not found at $f — skipping Firefox update"
|
||||
fi
|
||||
fi
|
||||
|
||||
[[ $updated -eq 0 ]] && echo "No manifest found. Run scripts/install.sh first." && exit 1
|
||||
echo "Done. Restart Chrome."
|
||||
echo "Done. Restart your browser."
|
||||
|
||||
Reference in New Issue
Block a user