diff --git a/background.js b/background.js index c01ee49..ef7d70c 100644 --- a/background.js +++ b/background.js @@ -8,15 +8,37 @@ * - 管理扩展状态和配置 */ -// 导入兼容层 -importScripts("webext-compat.js"); +// 对于Firefox Manifest V2,webext-compat.js 通过manifest加载 +// 对于Chrome Manifest V3,通过importScripts加载 +if (typeof importScripts !== "undefined") { + try { + importScripts("webext-compat.js"); + } catch (e) { + console.log("Running in Firefox/Manifest V2 environment"); + } +} // 确保兼容层可用 if (typeof webext === "undefined") { - // 在非模块环境中,兼容层应该已经通过脚本标签加载 console.error("WebExt compatibility layer not found"); + // 尝试使用全局的browser或chrome API + if (typeof browser !== "undefined") { + console.log("Using Firefox browser API directly"); + self.webext = browser; + self.webextFlavor = { soup: new Set(["firefox"]) }; + } else if (typeof chrome !== "undefined") { + console.log("Using Chrome API directly"); + self.webext = chrome; + self.webextFlavor = { soup: new Set(["chromium"]) }; + } } +// 确认API可用性 +console.log("Background script initializing..."); +console.log("WebExt API available:", typeof webext !== "undefined"); +console.log("Storage API available:", webext && webext.storage ? "yes" : "no"); +console.log("Runtime API available:", webext && webext.runtime ? "yes" : "no"); + /** * 平台配置定义 * 支持的下载加速平台列表 @@ -226,12 +248,26 @@ const DEFAULT_SETTINGS = { webext.runtime.onInstalled.addListener(async () => { console.log("Xget Now 已安装"); - // 使用本地存储而不是同步存储以确保兼容性 - const storageAPI = webext.storage.sync || webext.storage.local; + // 对于Firefox,优先使用local存储,因为sync可能不可用或有限制 + const isFirefox = + webextFlavor && webextFlavor.soup && webextFlavor.soup.has("firefox"); + const storageAPI = isFirefox + ? webext.storage.local + : webext.storage.sync || webext.storage.local; - // 如果尚未设置,则设置默认设置 - const settings = await storageAPI.get(DEFAULT_SETTINGS); - await storageAPI.set(settings); + try { + // 如果尚未设置,则设置默认设置 + const settings = await storageAPI.get(DEFAULT_SETTINGS); + await storageAPI.set(settings); + } catch (error) { + console.error("初始化设置时出错:", error); + // 尝试使用local storage作为后备 + try { + await webext.storage.local.set(DEFAULT_SETTINGS); + } catch (localError) { + console.error("使用本地存储初始化设置时出错:", localError); + } + } }); // 防止监听器被多次注册 @@ -253,7 +289,12 @@ function handleDownload(downloadItem, suggest) { async function processDownloadRedirect(downloadItem) { try { - const storageAPI = webext.storage.sync || webext.storage.local; + // 对于Firefox,优先使用local存储 + const isFirefox = + webextFlavor && webextFlavor.soup && webextFlavor.soup.has("firefox"); + const storageAPI = isFirefox + ? webext.storage.local + : webext.storage.sync || webext.storage.local; const settings = await storageAPI.get(DEFAULT_SETTINGS); // 检查扩展是否已启用并配置了域名 @@ -324,37 +365,81 @@ function transformUrlLegacy(url, settings) { } // 监听来自弹出窗口/选项的消息 -webext.runtime.onMessage.addListener((request, sender, sendResponse) => { - const storageAPI = webext.storage.sync || webext.storage.local; +const messageListener = (request, sender, sendResponse) => { + console.log("Received message:", request.action); + + // 对于Firefox,优先使用local存储,因为sync可能不可用或有限制 + const isFirefox = + webextFlavor && webextFlavor.soup && webextFlavor.soup.has("firefox"); + const storageAPI = isFirefox + ? webext.storage.local + : webext.storage.sync || webext.storage.local; if (request.action === "getSettings") { - storageAPI.get(DEFAULT_SETTINGS).then(sendResponse); - return true; - } else if (request.action === "saveSettings") { - storageAPI.set(request.settings).then(async () => { - // 通知相关标签页刷新 + // 使用Promise处理异步操作 + (async () => { try { - const tabs = await webext.tabs.query({ - url: Object.values(PLATFORMS).map((platform) => platform.base + "/*"), - }); - - for (const tab of tabs) { - try { - await webext.tabs.sendMessage(tab.id, { - action: "showNotification", - message: "设置已更新!点击刷新页面", - showRefreshButton: true, - }); - } catch (error) { - // 标签页可能没有加载内容脚本,忽略 - } - } + const settings = await storageAPI.get(DEFAULT_SETTINGS); + console.log("Settings retrieved:", settings); + sendResponse(settings || DEFAULT_SETTINGS); } catch (error) { - console.log("无法通知标签页设置更新"); + console.error("获取设置时出错:", error); + sendResponse(DEFAULT_SETTINGS); } + })(); + return true; // 保持消息通道开放 + } else if (request.action === "saveSettings") { + // 确保设置对象有效 + const settingsToSave = { + ...DEFAULT_SETTINGS, + ...request.settings, + }; - sendResponse({ success: true }); - }); - return true; + (async () => { + try { + await storageAPI.set(settingsToSave); + console.log("Settings saved successfully"); + + // 通知相关标签页刷新 + try { + const tabs = await webext.tabs.query({ + url: Object.values(PLATFORMS).map( + (platform) => platform.base + "/*" + ), + }); + + for (const tab of tabs) { + try { + await webext.tabs.sendMessage(tab.id, { + action: "showNotification", + message: "设置已更新!点击刷新页面", + showRefreshButton: true, + }); + } catch (error) { + // 标签页可能没有加载内容脚本,忽略 + } + } + } catch (error) { + console.log("无法通知标签页设置更新"); + } + + sendResponse({ success: true }); + } catch (error) { + console.error("保存设置时出错:", error); + sendResponse({ success: false, error: error.message }); + } + })(); + return true; // 保持消息通道开放 } -}); + + // 未知消息 + return false; +}; + +// 添加消息监听器 +if (webext && webext.runtime && webext.runtime.onMessage) { + webext.runtime.onMessage.addListener(messageListener); + console.log("Message listener registered"); +} else { + console.error("Cannot register message listener - runtime API not available"); +} diff --git a/firefox-compat.js b/firefox-compat.js new file mode 100644 index 0000000..a6edbb8 --- /dev/null +++ b/firefox-compat.js @@ -0,0 +1,86 @@ +/** + * Firefox 特定兼容性修复 + * 直接使用 browser API 处理 Firefox 中的消息传递问题 + */ + +// 在 Firefox 中,直接使用 browser API +if ( + typeof browser !== "undefined" && + browser.runtime && + browser.runtime.sendMessage +) { + console.log("Firefox environment detected, using native browser API"); + + // 为popup.js提供一个简化的API + window.firefoxAPI = { + sendMessage: function (message) { + return new Promise((resolve, reject) => { + try { + browser.runtime.sendMessage(message, (response) => { + if (browser.runtime.lastError) { + console.error( + "Firefox sendMessage error:", + browser.runtime.lastError + ); + reject(browser.runtime.lastError); + } else { + resolve(response); + } + }); + } catch (error) { + console.error("Firefox sendMessage exception:", error); + reject(error); + } + }); + }, + + getSettings: async function () { + try { + return await browser.storage.local.get({ + enabled: true, + xgetDomain: "xget.xi-xu.me", + enabledPlatforms: { + gh: true, + gl: true, + gitea: true, + codeberg: true, + sf: true, + aosp: true, + hf: true, + npm: true, + pypi: true, + "pypi-files": true, + conda: true, + "conda-community": true, + maven: true, + apache: true, + gradle: true, + rubygems: true, + cran: true, + cpan: true, + ctan: true, + golang: true, + nuget: true, + crates: true, + packagist: true, + arxiv: true, + fdroid: true, + }, + }); + } catch (error) { + console.error("Failed to get settings from storage:", error); + throw error; + } + }, + + saveSettings: async function (settings) { + try { + await browser.storage.local.set(settings); + return { success: true }; + } catch (error) { + console.error("Failed to save settings to storage:", error); + return { success: false, error: error.message }; + } + }, + }; +} diff --git a/manifest-firefox.json b/manifest-firefox.json index b0adf4a..988e291 100644 --- a/manifest-firefox.json +++ b/manifest-firefox.json @@ -1,31 +1,27 @@ { - "manifest_version": 2, - "name": "Xget Now", - "version": "2.0.4", - "description": "为 Firefox 浏览器提供的 Xget 下载加速扩展,支持 GitHub、GitLab、npm、PyPI 等众多平台的文件下载加速", + "background": { + "persistent": true, + "scripts": ["webext-compat.js", "background.js"] + }, "browser_action": { "default_icon": { + "128": "icons/icon128.png", "16": "icons/icon16.png", "32": "icons/icon32.png", - "48": "icons/icon48.png", - "128": "icons/icon128.png" + "48": "icons/icon48.png" }, "default_popup": "popup.html", "default_title": "Xget Now" }, - "background": { - "scripts": [ - "webext-compat.js", - "background.js" - ], - "persistent": false + "browser_specific_settings": { + "gecko": { + "id": "i@xi-xu.me", + "strict_min_version": "109.0" + } }, "content_scripts": [ { - "js": [ - "webext-compat.js", - "content.js" - ], + "js": ["webext-compat.js", "content.js"], "matches": [ "https://github.com/*", "https://gitlab.com/*", @@ -56,6 +52,15 @@ "run_at": "document_end" } ], + "description": "为 Firefox 浏览器提供的 Xget 下载加速扩展,支持 GitHub、GitLab、npm、PyPI 等众多平台的文件下载加速", + "icons": { + "128": "icons/icon128.png", + "16": "icons/icon16.png", + "32": "icons/icon32.png", + "48": "icons/icon48.png" + }, + "manifest_version": 2, + "name": "Xget Now", "permissions": [ "downloads", "storage", @@ -86,19 +91,6 @@ "https://arxiv.org/*", "https://f-droid.org/*" ], - "icons": { - "16": "icons/icon16.png", - "32": "icons/icon32.png", - "48": "icons/icon48.png", - "128": "icons/icon128.png" - }, - "web_accessible_resources": [ - "icons/*" - ], - "browser_specific_settings": { - "gecko": { - "id": "i@xi-xu.me", - "strict_min_version": "109.0" - } - } -} \ No newline at end of file + "version": "2.0.4", + "web_accessible_resources": ["icons/*"] +} diff --git a/popup.html b/popup.html index eae6b03..beb6d0e 100644 --- a/popup.html +++ b/popup.html @@ -618,6 +618,7 @@ + diff --git a/popup.js b/popup.js index 4b1f668..752e6c8 100644 --- a/popup.js +++ b/popup.js @@ -9,17 +9,30 @@ */ document.addEventListener("DOMContentLoaded", async () => { - // 确保兼容层可用 - if (typeof webext === "undefined") { - console.error("WebExt compatibility layer not found in popup"); + // 确保有可用的API + if ( + typeof webext === "undefined" && + typeof browser === "undefined" && + !window.firefoxAPI + ) { + console.error("No compatible extension API found"); + showStatus("扩展API加载失败", "error"); return; } - // 加载当前设置 - await loadSettings(); + // 延迟执行以确保background脚本已准备就绪 + setTimeout(async () => { + try { + // 加载当前设置 + await loadSettings(); - // 设置事件监听器 - setupEventListeners(); + // 设置事件监听器 + setupEventListeners(); + } catch (error) { + console.error("Initialization error:", error); + showStatus("初始化失败,请重新打开扩展", "error"); + } + }, 100); }); /** @@ -27,9 +40,41 @@ document.addEventListener("DOMContentLoaded", async () => { */ async function loadSettings() { try { - const settings = await webext.runtime.sendMessage({ - action: "getSettings", - }); + console.log("Loading settings..."); + + let settings; + + // Firefox 特殊处理 + if (window.firefoxAPI && typeof browser !== "undefined") { + console.log("Using Firefox direct storage API"); + try { + // 首先尝试消息传递 + settings = await window.firefoxAPI.sendMessage({ + action: "getSettings", + }); + } catch (msgError) { + console.log( + "Message passing failed, using direct storage access:", + msgError + ); + // 如果消息传递失败,直接从存储读取 + settings = await window.firefoxAPI.getSettings(); + } + } else if (webext && webext.runtime && webext.runtime.sendMessage) { + // 标准 webext API + console.log("Using standard webext API"); + settings = await webext.runtime.sendMessage({ + action: "getSettings", + }); + } else { + throw new Error("No compatible API available"); + } + + console.log("Settings received:", settings); + + if (!settings) { + throw new Error("No response from background script"); + } // 使用当前设置更新 UI const domainValue = settings.xgetDomain || ""; @@ -301,12 +346,34 @@ async function saveSettings() { settings.xgetDomain = cleanupDomain(settings.xgetDomain); } - const response = await webext.runtime.sendMessage({ - action: "saveSettings", - settings: settings, - }); + let response; - if (response.success) { + // Firefox 特殊处理 + if (window.firefoxAPI && typeof browser !== "undefined") { + console.log("Saving settings using Firefox API"); + try { + // 首先尝试消息传递 + response = await window.firefoxAPI.sendMessage({ + action: "saveSettings", + settings: settings, + }); + } catch (msgError) { + console.log("Message passing failed, using direct storage:", msgError); + // 如果消息传递失败,直接写入存储 + response = await window.firefoxAPI.saveSettings(settings); + } + } else if (webext && webext.runtime && webext.runtime.sendMessage) { + // 标准 webext API + console.log("Saving settings using standard webext API"); + response = await webext.runtime.sendMessage({ + action: "saveSettings", + settings: settings, + }); + } else { + throw new Error("No compatible API available for saving settings"); + } + + if (response && response.success) { // 显示适当的状态 if (!settings.xgetDomain && settings.enabled) { showStatus("请配置你的 Xget 域名", "error"); @@ -315,6 +382,13 @@ async function saveSettings() { } else { showStatus("✅ 设置已保存!查看页面通知中的刷新按钮", "success"); } + } else if (response && response.error) { + console.error("保存设置失败:", response.error); + showStatus("保存设置时出错: " + response.error, "error"); + } else { + // 如果没有响应,可能是消息传递失败 + console.error("未收到后台脚本的响应"); + showStatus("保存设置时出错:无法与后台脚本通信", "error"); } } catch (error) { console.error("保存设置时出错:", error);