访问自己做的网站吗,怎么做网页表格,正规的合肥网站建设价格,网站建设营销的公司Chrome 浏览器插件获取网页 iframe 中的 window 对象
前言
之前写了篇《Chrome 浏览器插件获取网页 window 对象》文章#xff0c;是获取当前页面的 window 对象#xff0c;但是有些页面是嵌入 iframe 的#xff0c;特别是系统项目主域一样#xff0c;那就也需要获取 ifr…Chrome 浏览器插件获取网页 iframe 中的 window 对象
前言
之前写了篇《Chrome 浏览器插件获取网页 window 对象》文章是获取当前页面的 window 对象但是有些页面是嵌入 iframe 的特别是系统项目主域一样那就也需要获取 iframe 内部的 window 对象数据而且还不能重复加载 content html 页面。这个时候就需要对 content_script 的 js 文件进行特殊处理了。
一、需求整理
1. 没有 iframe 内嵌
可以参考 《Chrome 浏览器插件获取网页 window 对象》文章
2. 嵌套一个 iframe
2.1. 页面如下
[外链图片转存中…(img-EUQWEaju-1734921003172)]
2.2. Parent 页面对象数据
script
window.coverageData {name: parent,data: {a: parent}
}
/script2.3. Child 页面对象数据
script
window.coverageData {name: child1,data: {a: child}
}
/script3. 嵌套多个 Iframe
3.1. 页面如下
[外链图片转存中…(img-DEdTomCY-1734921003172)]
3.2. Child2 页面对象数据
scriptwindow.coverageData {name: child2,data: {a: child2}}
/script二、需求实现
我们就用 《Chrome 浏览器插件获取网页 window 对象》文章中的第一种方案使用两个 JS通过 postMessage 进行消息通讯获取 window 对象数据。
1. 新建项目文件
.
├── assets
│ └── icon.png
├── index.js
├── lucky.js
├── manifest.json
└── service-worker.jsindex.js通过 content_scripts 引入lucky.js通过 index.js 文件插入当前页面的 head 标签中
2. manifest.json 文件
{manifest_version: 3,name: Get Window Data,version: 0.0.1,description: get window data,action: {default_title: Get Window Data,default_icon: assets/icon.png},background: {service_worker: service-worker.js,type: module},content_scripts: [{js: [index.js],matches: [http://127.0.0.1:*/*,http://localhost:*/*],all_frames: true,run_at: document_end}],host_permissions: [http://127.0.0.1:*/*,http://localhost:*/*],permissions: [tabs,scripting,activeTab],web_accessible_resources: [{resources: [lucky.js],matches: [http://127.0.0.1:*/*, http://localhost:*/*],use_dynamic_url: false}]
}content_scripts 一定要设置 all_frames 为 true这样才可以透传 iframematches 匹配的是本地域名根据项目需要自行修改 host_permissions匹配的是本地域名根据项目需要自行修改permissions需要用到的权限根据项目需要自行修改web_accessible_resources所有需要在插件代码里面用到的文件都需要加在 resources 中不加这个 lucky.js 不能嵌入页面。
3. lucky.js 文件
/*** 发送 coverage data 数据* param {boolean} init 是否是初始化数据*/
const sendCoverageData (init false) {window.postMessage({type: coverage-data,data: window.coverageData,location: {href: window.location.href,hostname: window.location.hostname,host: window.location.host,pathname: window.location.pathname,protocol: window.location.protocol,port: window.location.port,search: window.location.search,hash: window.location.hash,origin: window.location.origin,domain: document.domain,title: document.title},init})
}
console.log(luckyjs, window.self window.top, window.self window.top)
// JS coverage data
sendCoverageData(true)/*** 监听 message 并进行处理*/
window.addEventListener(message, (event) {if (event.data?.type get-coverage) {sendCoverageData()}
})sendCoverageData通过 postMessage 发送消息 init 是值是否第一次发送消息包含的数据为 window 下的 coverageData、location 对象type 类型init 字段不可以直接把 location 传过来会报错的 addEventListener 进行消息监听再次发送数据
3.1. 直传 location 报错
Uncaught DataCloneError: Failed to execute ‘postMessage’ on ‘Window’: Location object could not be cloned.
3.1.1. 页面报错消息
[外链图片转存中…(img-0UKCS9xx-1734921003172)]
3.1.2. 插件报错消息
[外链图片转存中…(img-UgOegQTJ-1734921003172)]
3.2. 为什么要传 location 数据
因为可能存在多个 iframe可以通过 location 进行区分
4. index.js 文件
/*** 添加 script 标签* param {string} url 路径* param {string} id script ID*/
const addScript (url, id) {const script document.createElement(script)id (script.id id)script.src chrome.runtime.getURL(url)document.head.appendChild(script)
}/*** 添加 JS 和事件监听*/
const addJSAndEventListener async () {// 监听从页面上下文发回的消息window.addEventListener(message, (event) {console.log(event.data, event.data)if (event.data?.type coverage-data) {}})addScript(lucky.js, coverage-script)
}addJSAndEventListener()
addScript添加 JS 文件把 lucky.js 添加到 head 标签中addEventListener消息监听
5. 安装插件
[外链图片转存中…(img-BKvrYSvE-1734921003172)]
6. window 数据
6.1. 当前页面 console 日志
[外链图片转存中…(img-u1h1mu7y-1734921003172)]
6.2. 当前页面插件 console 日志
6.2.1. 点击下面选项可以插件插件 index.js 的 console 日志
[外链图片转存中…(img-xzqEK568-1734921003172)]
6.2.2. console 日志
[外链图片转存中…(img-IU7N0A26-1734921003172)]
6.3. iframe 页面 console 日志
[外链图片转存中…(img-RufeHsSV-1734921003173)]
6.4. iframe 页面插件 console 日志
6.4.1. 选择当前 iframe 下的插件
[外链图片转存中…(img-7Nyz7P4e-1734921003173)]
6.4.2. console 日志
[外链图片转存中…(img-z4TNdIqI-1734921003173)]
7. 把数据传给 service-worker
7.1. service-worker.js 文件
/*** service worker 监听 接收消息*/
chrome.runtime.onMessage.addListener((message, sender, sendResponse) {console.log(message, message)switch (message.action) {// 从 content 发送消息到 SW发送数据case fromContent2SW-sendCoverage: {// todobreak}default: {break}}sendResponse()return false
})
7.2. service-worker 背景日志
[外链图片转存中…(img-DxqqjTnj-1734921003173)]
8. 嵌套多个 iframe
8.1. 查看页面
[外链图片转存中…(img-m5ot8wmH-1734921003173)]
8.2. service-worker 日志
[外链图片转存中…(img-PcuxPrOs-1734921003173)]
三、收集 coverage 数据并展示在 popup 中
[外链图片转存中…(img-qyZTcu1f-1734921003173)]
1. 增加 popup.html 和 popup.js 文件
.
├── assets
│ └── icon.png
├── index.js
├── lucky.js
├── manifest.json
├── popup.html
├── popup.js
└── service-worker.js1.1. popup.html 文件内容
!DOCTYPE html
html langen
headmeta charsetUTF-8meta nameviewport contentwidthdevice-width, initial-scale1.0titlePopup/titlestyle*{padding: 0;margin: 0;}body{width: 400px;max-height: 300px;min-height: 200px;}header{text-align: center;margin-bottom: 10px;}main{padding: 0 20px;#get_window_but{margin-bottom: 10px;}li{margin-bottom: 10px;word-break: break-all;list-style: none;}}/style
/head
bodyheaderh1Popup/h1/headermainbutton idget_window_but获取 window 数据/buttonul idwindow_coverage/ul/main
/body
script srcpopup.js/script
/html1.2. popup.js 文件内容
/*** 事件监听*/
chrome.runtime.onMessage.addListener((e, _, sendResponse) {switch (e.action) {case fromSW2Popup-sendCoverage: {const coverageUl document.getElementById(window_coverage)const li document.createElement(li)li.innerHTML divurl: ${e.message.location.href}/divdivcoverage: ${e.message.data ? JSON.stringify(e.message.data) : }/divcoverageUl.appendChild(li)break}default:break}sendResponse()return false
})const get_window_but document.getElementById(get_window_but)/*** but 按钮事件*/
get_window_but.onclick async () {const tabId await getCurrentTabId()// 从 popup 发送消息到 SWtabId chrome.runtime.sendMessage({action: fromPopup2SW-getWindowData,message: {tabId}})
}/*** 获取当前活动页面的 id* returns {string} tabId*/
const getCurrentTabId async () {const tabs await chrome.tabs.query({ active: true, currentWindow: true });return tabs tabs.length 0 ? tabs[0].id :
}addListener事件监听监听从 SW 发送到 popup 的消息把消息生成 li 在 append 到 ul 中onclick按钮点击事件发送消息到 SWgetCurrentTabId获取当前活动的页面的 tabId
2. manifest.json 文件
action: {default_title: Get Window Data,default_icon: assets/icon.png,default_popup: popup.html
},增加 default_popup 字段
3. index.js 文件
/*** 添加 script 标签* param {string} url 路径* param {string} id script ID*/
const addScript (url, id) {const script document.createElement(script)id (script.id id)script.src chrome.runtime.getURL(url)document.head.appendChild(script)
}/*** 添加 JS 和事件监听*/
const addJSAndEventListener async () {// 监听从页面上下文发回的消息window.addEventListener(message, (event) {if (event.data?.type coverage-data) {// 从 content 脚本获取到 coverage 数据后发送给 SWchrome.runtime.sendMessage({action: fromContent2SW-sendCoverage,message: {...event.data}})}})addScript(lucky.js, coverage-script)
}addJSAndEventListener()// 消息监听
chrome.runtime.onMessage.addListener((e, _, sendResponse) {switch (e.action) {// 从 SW 发送消息到 content 脚本获取 coverage 数据case fromSW2Content-getWindowData: {window.postMessage({type: get-coverage})break}default:break}sendResponse()return false
})addListener消息监听并进行 postmessage 消息传递给 lucky.js
4. lucky.js 文件
// sendCoverageData(true)因为我们是按钮点击在获取所以可以把初始化就获取数据注释掉
5. service-worker.js
/*** service worker 监听 接收消息*/
chrome.runtime.onMessage.addListener((message, sender, sendResponse) {switch (message.action) {// 从 content 发送消息到 SW发送数据case fromContent2SW-sendCoverage: {// 从 SW 发送消息到 popup发送数据chrome.runtime.sendMessage({action: fromSW2Popup-sendCoverage,message: {...message.message}})break}// 从 popup 发送消息到 SW获取数据case fromPopup2SW-getWindowData: {// 从 SW 发送消息到 content获取数据chrome.tabs.sendMessage(message.message.tabId,{action: fromSW2Content-getWindowData,message: {}},{},() {})break;}default: {break}}sendResponse()return false
})
接收 popup 的消息并发送到 content 文件 需要 tabId 字段 从 content 接收消息并发送到 popup 页面service-worker 对两者发送消息的方式不一样 content 因为是在页面中所以需要 tabIdpopup 则不需要 tabId
6. 效果展示
[外链图片转存中…(img-JdmxovqK-1734921003173)]
6.1. 小问题
多次点击会重复渲染
[外链图片转存中…(img-itJlga8y-1734921003173)]
我这里就不做处理需要的话自己判断处理即可
四、总结
获取逻辑和 《Chrome 浏览器插件获取网页 window 对象》中的方案一一样有兴趣的可以试下其他方案我这是本地 iframe URL如果你的 URL 是网页链接可以在 index.js 中嵌入 lucky.js 做延迟处理如果你的 iframe URL 是动态的比如点击 tab切换 URL则可以在 index.js 中进行 MutationObserver 监听如果你需要部分内容嵌入 iframe 中则可以使用 window.top window.self 判断是否是顶层源码【Gitee】