前言
最近有个需求,是在浏览器插件中获取 window 对象下的某个数据,当时觉得很简单,和 document 一样,直接通过嵌入 content_scripts 直接获取,然后使用 sendMessage 发送数据到插件就行了,结果发现不是这样滴...
在这里不推荐使用
runtime.executeScript进行注入,很可能会报错:
Refused to execute inline script because it violates the following Content Security Policy directive: "script-src 'self' 'wasm-unsafe-eval' 'inline-speculation-rules' http://localhost😗 http://127.0.0.1😗". Either the 'unsafe-inline' keyword, a hash ('sha256-P5exJBBLYN1KVh+CK9MkXvRal4ZQQu9VaKPvx4JuVLE='), or a nonce ('nonce-...') is required to enable inline execution.
Chrome 浏览器插件获取网页 window 对象(方案一)
Chrome 浏览器插件获取网页 window 对象(方案二)
一、两个文件,通过 CustomEvent 传递消息
1. 方案思路
- 新建两个
js文件,index.js和lucky.js - 在
content_scripts中嵌入lucky.js文件和index.js文件 - 在
index.js中通过window.dispatchEvent派发自定义custom event消息 - 在
index.js中通过addEventListener监听消息 - 在
lucky.js中通过addEventListener监听消息,再通过dispatchEvent派发消息
1.1. content_scripts 嵌入 JS 文件
一定要把 lucky.js 文件放在 index.js 文件前面
content_scripts 中添加 lucky.js 的时候需要加上 "world": "MAIN" 字段
world 为枚举类型
ISOLATED默认值- 此扩展程序所独有的执行环境
MAIN- 指定
DOM的主域,也就是与托管页面的JavaScript共享的执行环境
- 指定
1.2. 方案流程
流程图如下:

2. 获取内容
获取
window下的MyBlog字段
window.MyBlog = { juejin: 'https://juejin.cn/user/2409752520033768/posts', csdn: 'https://guoqiankun.blog.csdn.net/', 'chrome-blog': { netlify: 'https://gqk-extension.netlify.app/', github: 'https://18055975947.github.io/extension/' } }
3. 实现代码
3.1. index.js
/** * index 文件发送消息到 lucky.js 文件 * @param {string} type custom 类型 * @param {any} data 数据 */ const indexSendMessageToLucky = async (type, data) => { window.dispatchEvent(new CustomEvent('custom-index-type', { detail: { type, data } })) return new Promise((res) => { function handleResponse(e) { const detail = e.detail if (detail.type == type) { window.removeEventListener('custom-lucky-type', handleResponse) return res(detail.data) } } window.addEventListener('custom-lucky-type', handleResponse) }) } /** * 发送消息 */ const sendMessage = () => { function getMyBolg() { return window.MyBlog } indexSendMessageToLucky('run-index-fun', { function: getMyBolg.toString() }).then((res) => { console.log('res-->', res) }).catch((e) => { console.log('e', e) }) } /** * 初始化 */ const init = () => { // 插入 button 按钮 const button = document.createElement('button') button.innerText = '获取数据' button.id = 'chrome-ext-but' document.body.appendChild(button) button.onclick = () => { sendMessage() } // 初始化获取数据 sendMessage() } // 判断 window.top 和 self 是否相等,如果不相等,则不注入 if (window.top == window.self) { init() }
3.2. lucky.js
/** * 事件监听 */ window.addEventListener('custom-index-type', async (e) => { const { type, data } = e.detail switch (type) { case 'run-index-fun': { const fn = new Function(`return (${data.function})(...arguments)`) const rs = await fn(...(data.args ?? [])) luckySendMessageToIndex(type, rs) break } } }) /** * lucky 文件发送消息到 index.js 文件 * @param {string} type custom 类型 * @param {any} data 数据 */ const luckySendMessageToIndex = (type, data) => { window.dispatchEvent( new CustomEvent('custom-lucky-type', { detail: { type, data, file: 'lucky' } }) ) }
3.3. manifest.json
{ "manifest_version": 3, "name": "Get Winddow Object Field", "version": "1.0", "description": "Gets the field under window", "content_scripts": [ { "js": [ "lucky.js" ], "matches": ["http://localhost:*/*"], "run_at": "document_end", "world": "MAIN" }, { "js": [ "index.js" ], "matches": ["http://localhost:*/*"], "all_frames": true, "run_at": "document_end" } ], "background": { "service_worker": "service-worker.js" }, "host_permissions": [ "http://localhost:*/*" ], "permissions": [ ], "web_accessible_resources": [] }
3.4. 项目文件结构
. ├── index.html ├── index.js ├── lucky.js ├── manifest.json └── service-worker.js
3.5. 方案效果
在控制台中选择当前插件,即可查看获取的 window 下的 MyBlog 对象

4. 动态获取数据
4.1. 点击按钮

4.2. 数据返回

5. 代码地址
四、总结
1. 文章总结
- 获取当前页面下的 window 对象和 document 对象不一样,需要另外的处理方式
- 此次提供了三种方案,核心原理都是嵌入当前页面,通过消息派发和接收来获取数据
- 第一种通过 postMessage 的方式更为大家熟悉,自定义 Event 相对偏一点
- 三种方案的代码我都上传到 gitee/github 上了
2. 代码地址
- Gitee:https://gitee.com/gqk-chrome-extension/get-window-fields
- Github:https://github.com/gqk-chrome-extension/get-window-fields/tree/main