Last updated on

浏览器 AI 分屏助手:基于 Chrome Extension API 实现智能分屏方案


浏览器 AI 分屏助手:基于 Chrome Extension API 实现智能分屏方案

在日常开发和学习中,我们经常需要在网页内容和 AI 助手之间来回切换标签页——查文档时问 ChatGPT,看论文时用 AI 翻译,写代码时参考 AI 生成的示例。频繁的标签页切换不仅打断思路,还严重影响效率。

AI Sidebar Chat 是一款我开发的 Chrome 浏览器扩展,它通过浏览器 Extension API 实现了一键分屏功能:将当前网页与 AI 助手并排显示在同一个窗口中,无需切换标签页即可同时浏览和对话。

本文将从技术角度详细讲解这个扩展的实现原理、核心 API 使用方法以及架构设计思路。


一、技术方案选型

1.1 为什么选择浏览器扩展而非独立应用?

方案 优点 缺点
独立分屏应用 灵活度高,不受浏览器限制 需要单独安装,无法直接操作浏览器标签页
浏览器扩展 深度集成浏览器 API,可直接操作标签页 受浏览器扩展 API 能力限制
PWA 网页应用 跨平台,无需安装 无法控制浏览器标签页行为

浏览器扩展的优势在于可以直接使用 chrome.tabschrome.windows 等 API 操作标签页和窗口,这是其他方案无法实现的。

1.2 分屏实现的核心思路

浏览器的“分屏”本质上并不是真正的窗口分割,而是通过以下方式模拟:

  1. 方案 A:在当前标签页中注入 iframe,将 AI 页面嵌入侧边栏
  2. 方案 B:利用 chrome.tabs.create 创建新标签页,并通过 chrome.windows.update 调整窗口尺寸实现左右分屏
  3. 方案 C:使用 Chrome 的 Side Panel API(Chrome 114+)

方案 A 的问题:许多 AI 网站(如 ChatGPT)设置了 X-Frame-Options: DENY,禁止被 iframe 嵌入。

方案 C 的问题:Side Panel API 虽然原生支持侧边栏,但空间有限,且 API 兼容性要求较高。

最终选择方案 B:通过标签页 + 窗口尺寸控制实现分屏,兼容性最好,且不受目标网站的 iframe 策略限制。


二、核心架构设计

2.1 扩展结构

ai-sidebar-chat/
├── manifest.json          # 扩展配置文件(Manifest V3)
├── background.js          # Service Worker(后台脚本)
├── popup/
│   ├── popup.html         # 弹出窗口界面
│   ├── popup.js           # 弹出窗口逻辑
│   └── popup.css          # 样式
├── options/
│   ├── options.html       # 设置页面
│   └── options.js         # 设置逻辑
└── icons/
    ├── icon16.png
    ├── icon48.png
    └── icon128.png

2.2 Manifest V3 配置

{
  "manifest_version": 3,
  "name": "AI Sidebar Chat",
  "version": "1.0.0",
  "description": "一键将当前网页与 AI 助手并排显示,提升多任务处理效率",
  "permissions": [
    "tabs",
    "storage",
    "activeTab"
  ],
  "action": {
    "default_popup": "popup/popup.html",
    "default_icon": {
      "16": "icons/icon16.png",
      "48": "icons/icon48.png",
      "128": "icons/icon128.png"
    }
  },
  "background": {
    "service_worker": "background.js"
  }
}

关键权限说明

  • tabs:允许读取和操作标签页信息
  • storage:用于持久化用户设置(如选择的 AI 服务、分屏比例等)
  • activeTab:获取当前活动标签页的访问权限

三、核心功能实现

3.1 分屏逻辑的实现

分屏的核心逻辑分为三步:

  1. 获取当前活动标签页的信息(URL、标题)
  2. 在当前窗口中创建一个新标签页,打开 AI 网站
  3. 调整两个标签页的显示比例,实现左右分屏效果
// background.js - 分屏核心逻辑
async function createSplitScreen(aiUrl, ratio = 0.5) {
  // 获取当前活动标签页
  const [activeTab] = await chrome.tabs.query({
    active: true,
    currentWindow: true
  });

  if (!activeTab) return;

  // 获取当前窗口信息
  const currentWindow = await chrome.windows.getCurrent();

  // 计算左右面板宽度
  const totalWidth = currentWindow.width;
  const leftWidth = Math.floor(totalWidth * ratio);
  const rightWidth = totalWidth - leftWidth;

  // 调整当前窗口大小(左侧)
  await chrome.windows.update(currentWindow.id, {
    width: leftWidth,
    left: currentWindow.left
  });

  // 创建新窗口(右侧)并打开 AI 页面
  await chrome.windows.create({
    url: aiUrl,
    left: currentWindow.left + leftWidth,
    width: rightWidth,
    height: currentWindow.height,
    top: currentWindow.top,
    type: 'normal',
    focused: true
  });
}

3.2 标签页管理策略

分屏后需要管理两组标签页:原始网页和 AI 页面。当用户点击“关闭分屏”时,需要恢复原始状态:

// 记录分屏前的标签页状态
async function saveTabState(tabId, aiTabId) {
  await chrome.storage.session.set({
    splitScreenState: {
      originalTabId: tabId,
      aiTabId: aiTabId,
      timestamp: Date.now()
    }
  });
}

// 关闭分屏,恢复原始标签页
async function closeSplitScreen() {
  const { splitScreenState } = await chrome.storage.session.get('splitScreenState');
  if (!splitScreenState) return;

  const { originalTabId, aiTabId } = splitScreenState;

  // 关闭 AI 标签页
  try {
    await chrome.tabs.remove(aiTabId);
  } catch (e) {
    // 标签页可能已被手动关闭
    console.log('AI tab already closed');
  }

  // 聚焦到原始标签页
  try {
    await chrome.tabs.update(originalTabId, { active: true });
  } catch (e) {
    console.log('Original tab no longer exists');
  }

  // 清除状态
  await chrome.storage.session.remove('splitScreenState');
}

3.3 多 AI 服务支持

扩展内置了多个主流 AI 服务的配置,同时支持用户自定义添加:

// 内置 AI 服务配置
const BUILTIN_AI_SERVICES = [
  {
    id: 'chatgpt',
    name: 'ChatGPT',
    url: 'https://chat.openai.com',
    icon: 'chatgpt.png'
  },
  {
    id: 'deepseek',
    name: 'DeepSeek',
    url: 'https://chat.deepseek.com',
    icon: 'deepseek.png'
  },
  {
    id: 'wenxin',
    name: '文心一言',
    url: 'https://yiyan.baidu.com',
    icon: 'wenxin.png'
  },
  {
    id: 'tongyi',
    name: '通义千问',
    url: 'https://tongyi.aliyun.com',
    icon: 'tongyi.png'
  },
  {
    id: 'doubao',
    name: '豆包',
    url: 'https://www.doubao.com',
    icon: 'doubao.png'
  }
];

用户自定义的 AI 服务存储在 chrome.storage.sync 中,支持跨设备同步:

// 保存自定义 AI 服务
async function saveCustomAI(service) {
  const { customServices = [] } = await chrome.storage.sync.get('customServices');
  customServices.push({
    id: `custom_${Date.now()}`,
    name: service.name,
    url: service.url,
    icon: null,
    isCustom: true
  });
  await chrome.storage.sync.set({ customServices });
}

四、性能优化与用户体验

4.1 内存优化

浏览器扩展如果管理不当容易造成内存泄漏,特别是在频繁创建/销毁标签页的场景下。主要优化措施:

  1. 及时清理 Session 存储:关闭分屏后立即清除 chrome.storage.session 中的状态数据
  2. 避免重复监听器:Service Worker 可能被浏览器频繁唤醒,确保事件监听器不会重复注册
  3. 延迟加载:popup 界面按需渲染 AI 服务列表,避免一次性加载所有图标资源

4.2 分屏比例记忆

用户调整的分屏比例会通过 chrome.storage.sync 持久化,下次使用时自动恢复:

// 保存分屏比例
async function saveSplitRatio(ratio) {
  await chrome.storage.sync.set({ splitRatio: ratio });
}

// 读取分屏比例
async function getSplitRatio() {
  const { splitRatio = 0.5 } = await chrome.storage.sync.get('splitRatio');
  return splitRatio;
}

4.3 深浅主题与国际化

扩展支持浅色/深色主题切换和中英文双语界面。主题状态跟随系统设置,也可以手动切换:

// 检测系统主题偏好
const prefersDark = window.matchMedia('(prefers-color-scheme: dark)');
prefersDark.addEventListener('change', (e) => {
  document.body.classList.toggle('dark', e.matches);
});

五、适用场景

  • 学习研究:左侧打开论文/文档,右侧用 AI 解释难点概念
  • 编程开发:左侧查看技术文档,右侧让 AI 生成代码示例
  • 内容创作:左侧浏览参考素材,右侧用 AI 辅助写作
  • 翻译对比:左侧打开外文网页,右侧用 AI 实时翻译
  • 数据分析:左侧查看数据报表,右侧让 AI 分析趋势

六、总结与展望

AI Sidebar Chat 的核心技术并不复杂——主要依赖 Chrome Extension 的 tabswindowsstorage API。真正的挑战在于:

  1. 标签页状态管理:确保分屏和恢复过程稳定可靠
  2. 多 AI 服务兼容:不同 AI 网站的页面行为差异较大,需要兼容处理
  3. 用户体验打磨:分屏比例、主题切换、语言设置等细节决定了用户留存

未来计划加入的功能包括:

  • 支持 Chrome 原生 Side Panel API(Chrome 114+)
  • 快捷键绑定,进一步提升操作效率
  • AI 对话历史本地备份与导出

如果你对浏览器扩展开发感兴趣,也可以参考我的另一篇文章 MS-ToDo 插件开发实践


相关链接