Expanded extension support to include Firefox alongside Chromium browsers. Updated README with detailed installation, build, and troubleshooting instructions for both Chromium and Firefox, clarified browser compatibility, and improved cross-browser guidance throughout code comments and documentation. Minor terminology changes were made in scripts and workflow files to consistently refer to 'Chromium' instead of 'Chrome/Chromium'.
165 lines
4.7 KiB
JavaScript
165 lines
4.7 KiB
JavaScript
/**
|
|
* 平台特定的配置和检测
|
|
*
|
|
* 提供浏览器平台检测和特性识别功能:
|
|
* - 检测当前运行的浏览器类型和版本
|
|
* - 识别 Manifest 版本 (V2/V3)
|
|
* - 检测移动端环境
|
|
* - 识别开发版本
|
|
*/
|
|
|
|
/**
|
|
* 平台检测器
|
|
* 提供浏览器环境检测的核心功能
|
|
*/
|
|
const platformDetector = {
|
|
/**
|
|
* 检测当前浏览器平台
|
|
*
|
|
* @returns {Object} 平台检测结果
|
|
* @property {string} platform - 浏览器类型 (firefox/chrome/edge/opera/safari/unknown)
|
|
* @property {number} version - 浏览器主版本号
|
|
* @property {number} manifestVersion - Manifest 版本号
|
|
* @property {boolean} isMobile - 是否为移动端
|
|
* @property {boolean} isDevBuild - 是否为开发版本
|
|
*/
|
|
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;
|
|
|
|
// 根据扩展 URL 前缀检测浏览器类型
|
|
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 不支持动态调整弹窗大小
|
|
}
|
|
|
|
// 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;
|
|
}
|