前言
最近有個需求,是在瀏覽器外掛中獲取 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. 程式碼地址
- Gitee
- Github
四、總結
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
引用
- 【chrome extensions mv3透過content scripts注入/獲取原網站的window資料】
- 【CustomEvent:CustomEvent() 建構函式】
- 【Content_script world】