You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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权限。

关键说明

  1. Service Worker变量持久化:用chrome.storage.session存储窗口ID,避免Service Worker休眠后内存变量丢失。
  2. 权限差异:方案1需要system.display权限,方案2仅需基础的windows权限(默认已包含)。
  3. 兼容性:两种方案均支持Chrome 88+(MV3最低支持版本)。

内容的提问来源于stack exchange,提问作者kireSO

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.21 20:15:39