内置浏览器窗口
聊天消息中的 URL 自动识别为可点击链接,点击弹出独立 BrowserWindow 加载目标网站,自动嗅探页面中的视频资源并支持在线播放。
- 链接识别:
TextContent 组件自动解析消息文本中的 HTTP/HTTPS URL,渲染为蓝色可点击链接,派发 open-browser 自定义事件
- 独立窗口:BrowserWindow 直接加载目标 URL,原生窗口框架,使用独立
persist:browser session 持久化 Cookie/Storage
- 工具栏:前进/后退/刷新、地址栏(输入新 URL 跳转)、关闭窗口、系统浏览器打开(
shell.openExternal)、Ctrl+L 聚焦地址栏
- 持久登录态:
persist:browser 分区,所有浏览器窗口共享 Cookie,重启应用后登录态保持
三层视频嗅探
| 嗅探层 |
位置 |
方式 |
| webRequest URL |
主进程 onBeforeRequest |
正则匹配 .mp4/.m3u8/.mpd/.flv/.webm/.mkv/.mov/.avi |
| webRequest Content-Type |
主进程 onHeadersReceived |
匹配 video/*、audio/*、application/x-mpegURL、application/dash+xml |
| 主世界 JS 注入 |
executeJavaScript |
劫持 fetch/XMLHttpRequest + 扫描 <video>/<source> 标签,通过 window.postMessage 回传 |
M3U8 校验与结果展示
- M3U8 异步校验:嗅探到
.m3u8 链接后 fetch() 验证,检查响应内容含 #EXTM3U/#EXTINF → 标记 valid/invalid
- TS/M4S 分片过滤:
.ts/.m4s 流媒体分片直接过滤,不显示在嗅探列表
- 页面导航刷新:URL 跳转时自动清空旧结果,重新嗅探新页面
| 链接类型 |
状态 |
图标 |
点击行为 |
| MP4/MKV/WebM 等 |
— |
▶ 蓝 |
弹出播放器 + 复制链接 |
| M3U8 校验通过 |
valid |
▶ 蓝 |
弹出播放器 + 复制链接 |
| M3U8 校验失败 |
invalid |
🚫 灰 |
仅复制链接 |
| M3U8 校验中 |
checking |
⏳ 黄 |
仅复制链接 |
视频播放集成
- 弹出播放器:点击可播放条目 → 暂停页面中视频 → 新建 BrowserWindow 加载 VideoPlayer 组件(
?player=1&src=...)
- HLS/M3U8 支持:VideoPlayer 新增 HLS 动态解码(
import('hls.js') → hls.loadSource() + hls.attachMedia()),hls.js 未安装时回退 Safari 原生
- standalone 模式:
<VideoPlayer standalone> 解除内联尺寸限制(maxWidth 280→100%、maxHeight 200→100vh),自动播放
- 不可播放条目:仍可点击复制链接到剪贴板,蓝色高亮反馈 600ms
请求安全与反检测
- 请求头伪装:UA 替换为标准 Chrome 131,自动补齐 Referer
- 弹窗拦截:
window.open()/target="_blank" 全部在当前窗口内导航
- 独立 Session:
session.fromPartition('persist:browser'),主窗口 CSP 不影响浏览器窗口
- 反检测脚本(主世界注入):覆盖 11 项特征(
navigator.webdriver→false、补充 window.chrome、补全 navigator.plugins 等)
架构演进
| 尝试 |
问题 |
结论 |
<webview> + React |
DOM 对账冲突→ERR_ABORTED、焦点抢占 |
废弃 |
| BrowserView + 透明窗口 |
transparent:true→macOS 窗口消失 |
废弃 |
| preload 中 XHR/Fetch 劫持 |
contextIsolation:true 下只影响隔离世界 |
改为主世界 executeJavaScript |
all:initial CSS |
SVG 图标放大、继承混乱 |
改为精确属性重置 |
涉及文件
| 文件 |
说明 |
apps/desktop/src/preload/browser.ts |
新增 — 浏览器窗口 preload(工具栏 + 嗅探面板 + postMessage 监听) |
apps/desktop/src/main/index.ts |
7 个 browser IPC;主世界嗅探脚本注入;persist:browser session |
apps/desktop/src/preload/index.ts |
api.browser.{open, openExternally, openPlayer, onPlayVideoInChat} |
apps/desktop/src/renderer/src/components/MessageBubble.tsx |
TextContent:URL 识别 + open-browser 事件 |
apps/desktop/src/renderer/src/components/VideoPlayer.tsx |
standalone 模式 + HLS 动态解码 |
apps/desktop/src/renderer/src/App.tsx |
open-browser 监听 + ?player=1 播放器窗口 |
apps/desktop/electron.vite.config.ts |
preload 多入口(index.ts + browser.ts) |
apps/desktop/package.json |
新增 hls.js 依赖 |