@@ -62,7 +62,7 @@ This installs the host to `~/.bridgeswarm/` (or `%LOCALAPPDATA%\bridgeswarm\` on
|
|||||||
1. Open `chrome://extensions`
|
1. Open `chrome://extensions`
|
||||||
2. Enable **Developer mode**
|
2. Enable **Developer mode**
|
||||||
3. Drag & drop `~/Downloads/BridgeSwarm-1.0.0.zip` onto the page (or Load unpacked after extracting)
|
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
|
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`).
|
**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",
|
"path": "ABSOLUTE_PATH_TO_NATIVE_HOST",
|
||||||
"type": "stdio",
|
"type": "stdio",
|
||||||
"allowed_origins": [
|
"allowed_origins": [
|
||||||
"chrome-extension://fmcenppcipeikpnpopolicnllljclmmi/"
|
"chrome-extension://jhmbaojjfkkpoolhkoohklbjokdmbdpm/"
|
||||||
],
|
],
|
||||||
"allowed_extensions": [
|
"allowed_extensions": [
|
||||||
"bridgeswarm-58514e5bbfe0d5e3@example.org"
|
"bridgeswarm-2b4c4bed6fceb6de@example.org"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
"name": "BridgeSwarm",
|
"name": "BridgeSwarm",
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"description": "P2P Hyperswarm in the browser via native messaging host",
|
"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": [
|
"permissions": [
|
||||||
"nativeMessaging",
|
"nativeMessaging",
|
||||||
"storage",
|
"storage",
|
||||||
@@ -50,7 +50,7 @@
|
|||||||
},
|
},
|
||||||
"browser_specific_settings": {
|
"browser_specific_settings": {
|
||||||
"gecko": {
|
"gecko": {
|
||||||
"id": "bridgeswarm-58514e5bbfe0d5e3@example.org",
|
"id": "bridgeswarm-2b4c4bed6fceb6de@example.org",
|
||||||
"strict_min_version": "79.0"
|
"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,
|
"private": true,
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"setup": "node scripts/run-install.js",
|
"setup": "node scripts/run-install.js",
|
||||||
|
"generate:extension-id": "node scripts/generate-extension-id.js",
|
||||||
"build:host": "node scripts/build-host.js",
|
"build:host": "node scripts/build-host.js",
|
||||||
"build:protomux": "node scripts/bundle-protomux.js",
|
"build:protomux": "node scripts/bundle-protomux.js",
|
||||||
"build:hrpc": "node scripts/build-hrpc.js",
|
"build:hrpc": "node scripts/build-hrpc.js",
|
||||||
|
|||||||
Regular → Executable
+27
-12
@@ -1,8 +1,13 @@
|
|||||||
#!/usr/bin/env node
|
#!/usr/bin/env node
|
||||||
'use strict';
|
'use strict';
|
||||||
/**
|
/**
|
||||||
* Generates a new extension ID and updates manifest.json and com.bridgeswarm.json.
|
* Generates a new BridgeSwarm extension ID pair and updates:
|
||||||
* Run on install so each copy of the template gets a unique ID (no overwrites).
|
* - 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 crypto = require('crypto');
|
||||||
const fs = require('fs');
|
const fs = require('fs');
|
||||||
@@ -10,29 +15,24 @@ const path = require('path');
|
|||||||
|
|
||||||
const repoRoot = path.join(__dirname, '..');
|
const repoRoot = path.join(__dirname, '..');
|
||||||
const manifestPath = path.join(repoRoot, 'extension', 'manifest.json');
|
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');
|
const nativeManifestPath = path.join(repoRoot, 'com.bridgeswarm.json');
|
||||||
|
|
||||||
// Generate RSA 2048-bit key pair
|
|
||||||
const { publicKey } = crypto.generateKeyPairSync('rsa', {
|
const { publicKey } = crypto.generateKeyPairSync('rsa', {
|
||||||
modulusLength: 2048,
|
modulusLength: 2048,
|
||||||
publicKeyEncoding: { type: 'spki', format: 'der' },
|
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
|
// Chrome extension ID: first 16 bytes of SHA256(publicKey), each nibble → a–p
|
||||||
// (Chromium crx_id.py: HexToMPDecimal)
|
|
||||||
const hash = crypto.createHash('sha256').update(publicKey).digest();
|
const hash = crypto.createHash('sha256').update(publicKey).digest();
|
||||||
const chromeId = Array.from(hash.slice(0, 16))
|
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('');
|
.join('');
|
||||||
|
|
||||||
// Firefox ID: unique per install
|
|
||||||
const firefoxId = 'bridgeswarm-' + crypto.randomBytes(8).toString('hex') + '@example.org';
|
const firefoxId = 'bridgeswarm-' + crypto.randomBytes(8).toString('hex') + '@example.org';
|
||||||
|
|
||||||
// Base64-encode public key for manifest
|
|
||||||
const keyBase64 = publicKey.toString('base64');
|
const keyBase64 = publicKey.toString('base64');
|
||||||
|
|
||||||
// Update extension manifest
|
|
||||||
const manifest = JSON.parse(fs.readFileSync(manifestPath, 'utf8'));
|
const manifest = JSON.parse(fs.readFileSync(manifestPath, 'utf8'));
|
||||||
manifest.key = keyBase64;
|
manifest.key = keyBase64;
|
||||||
if (manifest.browser_specific_settings?.gecko) {
|
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');
|
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'));
|
const nativeManifest = JSON.parse(fs.readFileSync(nativeManifestPath, 'utf8'));
|
||||||
nativeManifest.allowed_origins = ['chrome-extension://' + chromeId + '/'];
|
nativeManifest.allowed_origins = ['chrome-extension://' + chromeId + '/'];
|
||||||
nativeManifest.allowed_extensions = [firefoxId];
|
nativeManifest.allowed_extensions = [firefoxId];
|
||||||
fs.writeFileSync(nativeManifestPath, JSON.stringify(nativeManifest, null, 2) + '\n');
|
fs.writeFileSync(nativeManifestPath, JSON.stringify(nativeManifest, null, 2) + '\n');
|
||||||
|
|
||||||
console.log('Generated extension ID:', chromeId, '(' + firefoxId + ')');
|
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"
|
$Downloads = "$env:USERPROFILE\Downloads"
|
||||||
$ManifestName = "com.bridgeswarm"
|
$ManifestName = "com.bridgeswarm"
|
||||||
$ExtVersion = "1.0.0"
|
$ExtVersion = "1.0.0"
|
||||||
$ChromeExtId = "fmcenppcipeikpnpopolicnllljclmmi"
|
# Must match extension/manifest.json "key" / gecko.id and com.bridgeswarm.json
|
||||||
$FirefoxExtId = "bridgeswarm[email protected]"
|
# (unique to BridgeSwarm — do not share with holesail-browser)
|
||||||
|
$ChromeExtId = "jhmbaojjfkkpoolhkoohklbjokdmbdpm"
|
||||||
|
$FirefoxExtId = "[email protected]"
|
||||||
|
|
||||||
$HostZip = "bridge-swarm-host-win32-x64.zip"
|
$HostZip = "bridge-swarm-host-win32-x64.zip"
|
||||||
$ExtZip = "BridgeSwarm-$ExtVersion.zip"
|
$ExtZip = "BridgeSwarm-$ExtVersion.zip"
|
||||||
|
|||||||
+4
-2
@@ -13,8 +13,10 @@ INSTALL_DIR="$HOME/.bridgeswarm"
|
|||||||
MANIFEST_NAME="com.bridgeswarm"
|
MANIFEST_NAME="com.bridgeswarm"
|
||||||
DOWNLOADS="$HOME/Downloads"
|
DOWNLOADS="$HOME/Downloads"
|
||||||
EXT_VERSION="1.0.0"
|
EXT_VERSION="1.0.0"
|
||||||
CHROME_EXT_ID="fmcenppcipeikpnpopolicnllljclmmi"
|
# Must match extension/manifest.json "key" / gecko.id and com.bridgeswarm.json
|
||||||
FIREFOX_EXT_ID="bridgeswarm[email protected]"
|
# (unique to BridgeSwarm — do not share with holesail-browser)
|
||||||
|
CHROME_EXT_ID="jhmbaojjfkkpoolhkoohklbjokdmbdpm"
|
||||||
|
FIREFOX_EXT_ID="[email protected]"
|
||||||
|
|
||||||
# ── Detect platform ────────────────────────────────────────────────────────────
|
# ── Detect platform ────────────────────────────────────────────────────────────
|
||||||
OS="$(uname -s | tr '[:upper:]' '[:lower:]')"
|
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
|
* Output: releases/BridgeSwarm-<version>.zip, releases/BridgeSwarm-<version>.xpi
|
||||||
* Excludes: protomux-entry.cjs, *.map
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
const fs = require('fs');
|
const fs = require('fs');
|
||||||
@@ -13,10 +14,8 @@ const REPO_ROOT = path.resolve(__dirname, '..');
|
|||||||
const EXT_DIR = path.join(REPO_ROOT, 'extension');
|
const EXT_DIR = path.join(REPO_ROOT, 'extension');
|
||||||
const RELEASES_DIR = path.join(REPO_ROOT, 'releases');
|
const RELEASES_DIR = path.join(REPO_ROOT, 'releases');
|
||||||
|
|
||||||
const EXCLUDE = new Set([
|
const EXCLUDE_NAMES = new Set(['protomux-entry.cjs']);
|
||||||
'protomux-entry.cjs',
|
const EXCLUDE_EXTS = new Set(['.map']);
|
||||||
'.map'
|
|
||||||
]);
|
|
||||||
|
|
||||||
function getVersion() {
|
function getVersion() {
|
||||||
const manifestPath = path.join(EXT_DIR, 'manifest.json');
|
const manifestPath = path.join(EXT_DIR, 'manifest.json');
|
||||||
@@ -34,8 +33,9 @@ function listExtensionFiles(dir, base = dir) {
|
|||||||
if (e.isDirectory()) {
|
if (e.isDirectory()) {
|
||||||
files.push(...listExtensionFiles(full, base));
|
files.push(...listExtensionFiles(full, base));
|
||||||
} else {
|
} else {
|
||||||
const skip = EXCLUDE.has(e.name) || [...EXCLUDE].some(x => x.startsWith('.') && rel.endsWith(x));
|
const ext = path.extname(e.name);
|
||||||
if (!skip) files.push({ full, rel });
|
if (EXCLUDE_NAMES.has(e.name) || EXCLUDE_EXTS.has(ext)) continue;
|
||||||
|
files.push({ full, rel });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return files;
|
return files;
|
||||||
@@ -51,7 +51,7 @@ function createZip(version) {
|
|||||||
archive.on('error', reject);
|
archive.on('error', reject);
|
||||||
archive.pipe(output);
|
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) {
|
for (const { full, rel } of files) {
|
||||||
archive.file(full, { name: rel });
|
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() {
|
async function main() {
|
||||||
const version = getVersion();
|
const version = getVersion();
|
||||||
console.log('BridgeSwarm version from manifest:', version);
|
console.log('BridgeSwarm version from manifest:', version);
|
||||||
@@ -71,12 +97,13 @@ async function main() {
|
|||||||
console.log('Created releases/');
|
console.log('Created releases/');
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log('Creating zip...');
|
|
||||||
try {
|
try {
|
||||||
|
console.log('Creating Chrome zip...');
|
||||||
const zipPath = await createZip(version);
|
const zipPath = await createZip(version);
|
||||||
console.log('Written:', zipPath);
|
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);
|
console.log('Written:', xpiPath);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error(err);
|
console.error(err);
|
||||||
|
|||||||
@@ -1,11 +1,43 @@
|
|||||||
# Update native host manifest with your Chrome extension ID (fix "Access forbidden").
|
# Update native host manifest with your Chrome extension ID (fix "Access forbidden").
|
||||||
# Usage: .\scripts\update-native-manifest-extension-id.ps1 YOUR_EXTENSION_ID
|
# Optionally pass a Firefox extension ID as the second argument.
|
||||||
param([Parameter(Mandatory=$true)] [string] $ExtensionId)
|
# 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 '/$', ''
|
$ExtensionId = $ExtensionId -replace '^chrome-extension://', '' -replace '/$', ''
|
||||||
$Origin = "chrome-extension://$ExtensionId/"
|
$Origin = "chrome-extension://$ExtensionId/"
|
||||||
$manifestFile = (Get-ItemProperty -Path "HKCU:\Software\Google\Chrome\NativeMessagingHosts\com.bridgeswarm" -ErrorAction SilentlyContinue).'(Default)'
|
$updated = $false
|
||||||
if (-not $manifestFile -or -not (Test-Path $manifestFile)) { Write-Host "Run scripts/install.ps1 first."; exit 1 }
|
|
||||||
|
$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 = Get-Content $manifestFile -Raw | ConvertFrom-Json
|
||||||
$m.allowed_origins = @($Origin)
|
$m.allowed_origins = @($Origin)
|
||||||
$m | ConvertTo-Json -Depth 4 | Set-Content $manifestFile -Encoding UTF8
|
$m | ConvertTo-Json -Depth 4 | Set-Content $manifestFile -Encoding UTF8
|
||||||
Write-Host "Updated $manifestFile. Restart Chrome."
|
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
|
#!/usr/bin/env bash
|
||||||
# Update native host manifest with your Chrome extension ID (fix "Access forbidden").
|
# 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
|
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%/}"
|
EXT_ID="${1#chrome-extension://}"; EXT_ID="${EXT_ID%/}"
|
||||||
ORIGIN="chrome-extension://${EXT_ID}/"
|
ORIGIN="chrome-extension://${EXT_ID}/"
|
||||||
|
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"
|
CHROME_DIR="$HOME/.config/google-chrome/NativeMessagingHosts"
|
||||||
CHROMIUM_DIR="$HOME/.config/chromium/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_DIR="$HOME/.mozilla/native-messaging-hosts"
|
||||||
MANIFEST_NAME="com.bridgeswarm"
|
fi
|
||||||
|
|
||||||
updated=0
|
updated=0
|
||||||
|
|
||||||
for dir in "$CHROME_DIR" "$CHROMIUM_DIR"; do
|
for dir in "$CHROME_DIR" "$CHROMIUM_DIR"; do
|
||||||
f="$dir/${MANIFEST_NAME}.json"
|
f="$dir/${MANIFEST_NAME}.json"
|
||||||
[[ ! -f "$f" ]] && continue
|
[[ ! -f "$f" ]] && continue
|
||||||
@@ -18,8 +30,24 @@ for dir in "$CHROME_DIR" "$CHROMIUM_DIR"; do
|
|||||||
else
|
else
|
||||||
sed -i.bak "s|\"chrome-extension://[^\"]*/\"|\"$ORIGIN\"|g" "$f" && rm -f "${f}.bak"
|
sed -i.bak "s|\"chrome-extension://[^\"]*/\"|\"$ORIGIN\"|g" "$f" && rm -f "${f}.bak"
|
||||||
fi
|
fi
|
||||||
echo "Updated $f"
|
echo "Updated $f (allowed_origins)"
|
||||||
updated=1
|
updated=1
|
||||||
done
|
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
|
[[ $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