This update introduces full Firefox support using a new manifest-firefox.json (Manifest V2), adds a webext-compat.js compatibility layer for unified API usage, and refactors all extension scripts (background.js, content.js, popup.js) to use the new webext API. The build and development process is automated with new Python scripts (build.py, dev.py), and GitHub Actions workflows are updated to support multi-platform build, test, and release. Platform detection and capability abstraction are added, and all relevant files and manifests are updated for cross-browser compatibility.
148 lines
4.0 KiB
JavaScript
148 lines
4.0 KiB
JavaScript
/**
|
|
* 平台特定的配置和检测
|
|
*/
|
|
|
|
// 检测当前平台和环境
|
|
const platformDetector = {
|
|
/**
|
|
* 检测当前浏览器平台
|
|
*/
|
|
detect() {
|
|
const manifest =
|
|
typeof browser !== "undefined" && browser.runtime
|
|
? browser.runtime.getManifest()
|
|
: chrome.runtime.getManifest();
|
|
|
|
const ua = navigator.userAgent;
|
|
const extURL =
|
|
typeof browser !== "undefined" && browser.runtime
|
|
? browser.runtime.getURL("")
|
|
: chrome.runtime.getURL("");
|
|
|
|
let platform = "unknown";
|
|
let version = 0;
|
|
|
|
if (extURL.startsWith("moz-extension://")) {
|
|
platform = "firefox";
|
|
const match = /Firefox\/(\d+)/.exec(ua);
|
|
version = match ? parseInt(match[1], 10) : 115;
|
|
} else if (extURL.startsWith("safari-web-extension://")) {
|
|
platform = "safari";
|
|
const match = /Version\/(\d+)/.exec(ua);
|
|
version = match ? parseInt(match[1], 10) : 15;
|
|
} else if (/\bEdg\/\b/.test(ua)) {
|
|
platform = "edge";
|
|
const match = /Edg\/(\d+)/.exec(ua);
|
|
version = match ? parseInt(match[1], 10) : 120;
|
|
} else if (/\bOPR\/\b/.test(ua)) {
|
|
platform = "opera";
|
|
const match = /OPR\/(\d+)/.exec(ua);
|
|
version = match ? parseInt(match[1], 10) : 120;
|
|
} else {
|
|
platform = "chrome";
|
|
const match = /Chrome\/(\d+)/.exec(ua);
|
|
version = match ? parseInt(match[1], 10) : 120;
|
|
}
|
|
|
|
return {
|
|
platform,
|
|
version,
|
|
manifestVersion: manifest.manifest_version,
|
|
isMobile: /\bMobile\b/.test(ua),
|
|
isDevBuild: /^\d+\.\d+\.\d+\D/.test(manifest.version),
|
|
};
|
|
},
|
|
|
|
/**
|
|
* 获取平台特定的能力
|
|
*/
|
|
getCapabilities(platformInfo = null) {
|
|
const info = platformInfo || this.detect();
|
|
|
|
const capabilities = {
|
|
// 基础能力
|
|
downloads: true,
|
|
storage: true,
|
|
tabs: true,
|
|
|
|
// 高级能力
|
|
declarativeNetRequest: false,
|
|
offscreen: false,
|
|
scripting: false,
|
|
|
|
// 特殊能力
|
|
popupResize: true,
|
|
contextMenus: true,
|
|
notifications: true,
|
|
};
|
|
|
|
// Firefox 特定能力
|
|
if (info.platform === "firefox") {
|
|
capabilities.webRequest = true;
|
|
capabilities.contentSecurityPolicy = false; // 在 Manifest V2 中有限制
|
|
capabilities.popupResize = false; // Firefox 不支持动态调整弹窗大小
|
|
}
|
|
|
|
// Chrome/Chromium 特定能力
|
|
if (
|
|
info.platform === "chrome" ||
|
|
info.platform === "edge" ||
|
|
info.platform === "opera"
|
|
) {
|
|
if (info.manifestVersion === 3) {
|
|
capabilities.declarativeNetRequest = true;
|
|
capabilities.offscreen = info.version >= 109;
|
|
capabilities.scripting = true;
|
|
capabilities.webRequest = false; // MV3 中 webRequest 被限制
|
|
} else {
|
|
capabilities.webRequest = true;
|
|
}
|
|
}
|
|
|
|
// Safari 特定能力
|
|
if (info.platform === "safari") {
|
|
capabilities.notifications = false; // Safari 扩展通知支持有限
|
|
capabilities.contextMenus = false; // Safari 扩展上下文菜单支持有限
|
|
}
|
|
|
|
return capabilities;
|
|
},
|
|
|
|
/**
|
|
* 获取平台特定的限制
|
|
*/
|
|
getLimitations(platformInfo = null) {
|
|
const info = platformInfo || this.detect();
|
|
|
|
const limitations = {
|
|
maxStorageSize: Infinity,
|
|
maxDownloadConcurrency: 10,
|
|
requiresUserGesture: false,
|
|
contentScriptLimitations: [],
|
|
};
|
|
|
|
if (info.platform === "firefox") {
|
|
limitations.maxStorageSize = 5 * 1024 * 1024; // 5MB for local storage
|
|
limitations.contentScriptLimitations = [
|
|
"limited-eval", // eval() 受限
|
|
"no-dynamic-import", // 动态导入受限
|
|
];
|
|
}
|
|
|
|
if (info.platform === "safari") {
|
|
limitations.maxStorageSize = 10 * 1024 * 1024; // 10MB
|
|
limitations.requiresUserGesture = true; // 许多操作需要用户手势
|
|
limitations.maxDownloadConcurrency = 3; // 下载并发限制更严格
|
|
}
|
|
|
|
return limitations;
|
|
},
|
|
};
|
|
|
|
// 导出
|
|
if (typeof module !== "undefined" && module.exports) {
|
|
module.exports = { platformDetector };
|
|
} else {
|
|
window.platformDetector = platformDetector;
|
|
}
|