Chrome扩展v3迁移问题:点击图标时居中创建的窗口
解决Manifest V3中扩展窗口居中问题
问题根源
Manifest V3的后台逻辑运行在Service Worker环境中,不存在DOM和window对象,因此无法像MV2那样通过window.screen获取屏幕尺寸。同时,Service Worker会自动休眠,内存中的变量(比如原代码里的ftdWindow)会丢失,需要改用存储API持久化窗口ID。
解决方案
以下提供两种可行的屏幕尺寸获取方式,同时修正变量存储问题:
方案1:使用chrome.system.display.getInfo(推荐)
该API可直接获取所有显示器的详细尺寸信息,需要在manifest.json中添加对应权限。
步骤1:更新manifest.json
补充必要权限和配置:
{ "manifest_version": 3, "permissions": ["storage", "system.display"], "action": {}, "background": { "service_worker": "background.js" }, "web_accessible_resources": [ { "resources": ["WebContent/index.html"], "matches": ["<all_urls>"] } ] }
步骤2:修改后台脚本(background.js)
// Manifest Version 3 async function getCenteredPosition(width, height) { const displays = await chrome.system.display.getInfo(); // 获取主显示器信息,兼容多显示器场景 const primaryDisplay = displays.find(d => d.isPrimary) || displays[0]; const screenWidth = primaryDisplay.bounds.width; const screenHeight = primaryDisplay.bounds.height; return { left: Math.floor((screenWidth - width) / 2), top: Math.floor((screenHeight - height) / 2) }; } chrome.action.onClicked.addListener(async () => { // 从会话存储读取窗口ID,解决Service Worker休眠变量丢失问题 const storedWindow = await chrome.storage.session.get('ftdWindowId'); if (storedWindow.ftdWindowId) { try { // 尝试激活已有窗口 await chrome.windows.update(storedWindow.ftdWindowId, { focused: true }); return; } catch (err) { // 窗口已不存在,清除无效存储 await chrome.storage.session.remove('ftdWindowId'); } } // 获取保存的窗口尺寸 const result = await chrome.storage.sync.get(['windowSize']); let width = 1000; let height = 700; if (result.windowSize) { width = parseInt(result.windowSize.width); height = parseInt(result.windowSize.height); } // 计算居中位置 const { left, top } = await getCenteredPosition(width, height); // 创建新窗口 const newWindow = await chrome.windows.create({ url: chrome.runtime.getURL("WebContent/index.html"), type: "panel", left, top, width, height }); // 将窗口ID存入会话存储 await chrome.storage.session.set({ ftdWindowId: newWindow.id }); });
方案2:使用chrome.windows.getLastFocused(无需额外权限)
如果不想添加system.display权限,可以通过当前活跃窗口所在的屏幕尺寸计算居中位置:
async function getCenteredPosition(width, height) { const activeWindow = await chrome.windows.getLastFocused({ populate: false }); const screenWidth = activeWindow.screen.width; const screenHeight = activeWindow.screen.height; return { left: Math.floor((screenWidth - width) / 2), top: Math.floor((screenHeight - height) / 2) }; }
其余代码同方案1,无需修改manifest权限。
关键说明
- Service Worker变量持久化:用
chrome.storage.session存储窗口ID,避免Service Worker休眠后内存变量丢失。 - 权限差异:方案1需要
system.display权限,方案2仅需基础的windows权限(默认已包含)。 - 兼容性:两种方案均支持Chrome 88+(MV3最低支持版本)。
内容的提问来源于stack exchange,提问作者kireSO
相关产品推荐
相关产品推荐

