Firefox正式版加载未签名扩展

Firefox 安装扩展必须经过签名, 如果需要加载未签名的扩展, 有几种方法:

  1. 换dev/nightly版, 改 prefs.js(about:config - xpinstall.signatures.required)
  2. 用官方签名, 但可以不发布: https://support.mozilla.org/zh-CN/kb/add-ons-signing-firefox
  3. 用uc脚本, 自动加载调试模式 https://github.com/tsaost/autoload-temporary-addon
  4. 修改 omni.ja

node 版补丁

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
const { execSync } = require("child_process");
const fs = require("fs");
const path = require("path");
const os = require("os");

const FIREFOX_APP = "/Applications/Firefox.app";
const OMNI_PATH = path.join(
  FIREFOX_APP,
  "Contents/Resources/omni.ja"
);

const TMP_DIR = path.join(os.tmpdir(), "firefox_omni_patch");

// 1️⃣ 关闭 Firefox
function killFirefox() {
  try {
    execSync("pkill -f Firefox");
    console.log("✔ Firefox 已关闭");
  } catch (e) {
    console.log("ℹ Firefox 未运行");
  }
}

// 2️⃣ 解压 omni.ja
function extractOmni() {
  fs.rmSync(TMP_DIR, { recursive: true, force: true });
  fs.mkdirSync(TMP_DIR, { recursive: true });

  execSync(`bsdtar -xf "${OMNI_PATH}" -C "${TMP_DIR}"`);
  console.log("✔ 已解压 omni.ja");
}

// 3️⃣ 修改文件(你自己填逻辑)
function patchFile() {
  const target = path.join(
    TMP_DIR,
    "modules/addons/AddonSettings.sys.mjs"
  );

  if (!fs.existsSync(target)) {
    throw new Error("找不到目标文件: " + target);
  }

  let content = fs.readFileSync(target, "utf-8");

  // ⚠️ 这里留给你自己改
  // 示例:字符串替换(你自己决定怎么改)
  content = content.replace(
    'makeConstant("REQUIRE_SIGNING", true)',
    'makeConstant("REQUIRE_SIGNING", false)'
  ).replace(
    'makeConstant("LANGPACKS_REQUIRE_SIGNING", true)',
    'makeConstant("LANGPACKS_REQUIRE_SIGNING", false)'
  );

  fs.writeFileSync(target, content);
  console.log("✔ 已修改目标文件");
}

// 4️⃣ 重新打包
function repackOmni() {
  const newOmni = path.join(os.tmpdir(), "omni_new.ja");

  execSync(`cd "${TMP_DIR}" && zip -0 -r -X "../omni_new.ja" .`);
  console.log("✔ 已重新打包 omni.ja");

  return newOmni;
}

// 5️⃣ 替换
function replaceOmni(newOmni) {
  const backup = OMNI_PATH + ".bak";

  if (!fs.existsSync(backup)) {
    fs.copyFileSync(OMNI_PATH, backup);
    console.log("✔ 已备份 omni.ja");
  }

  fs.copyFileSync(newOmni, OMNI_PATH);
  console.log("✔ 已替换 omni.ja");
}

function applyPolicies() {
  const fs = require("fs");
  const path = require("path");

  const distDir = path.join(
    FIREFOX_APP,
    "Contents/Resources/distribution"
  );

  const policyFile = path.join(distDir, "policies.json");

  // 创建目录
  if (!fs.existsSync(distDir)) {
    fs.mkdirSync(distDir, { recursive: true });
    console.log("✔ 已创建 distribution 目录");
  }

  const policy = {
    policies: {
      DisableAppUpdate: true,
      ManualAppUpdateOnly: true,
    },
  };

  fs.writeFileSync(policyFile, JSON.stringify(policy, null, 2));

  console.log("✔ 已写入 policies.json(禁用自动更新)");
}

// 主流程
function main() {
  killFirefox();
  applyPolicies();
  extractOmni();
  patchFile();
  const newOmni = repackOmni();
  replaceOmni(newOmni);

  console.log("\n🎉 完成(是否能启动取决于 Firefox 校验)");
}

main();
build with Hugo, theme Stack, visits 0