当前位置: 首页 > news >正文

Chrome 浏览器插件获取网页 iframe 中的 window 对象

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'}
}
</script>
2.3. Child 页面对象数据
<script>
window.coverageData = {name: 'child1',data: {a: 'child'}
}
</script>

3. 嵌套多个 Iframe

3.1. 页面如下

[外链图片转存中…(img-DEdTomCY-1734921003172)]

3.2. Child2 页面对象数据
<script>window.coverageData = {name: 'child2',data: {a: 'child2'}}
</script>

二、需求实现

我们就用 《Chrome 浏览器插件获取网页 window 对象》文章中的第一种方案,使用两个 JS,通过 postMessage 进行消息通讯获取 window 对象数据。

1. 新建项目&文件

.
├── assets
│   └── icon.png
├── index.js
├── lucky.js
├── manifest.json
└── service-worker.js
  • index.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,这样才可以透传 iframe
    • matches 匹配的是本地域名,根据项目需要自行修改
  • 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.js
1.1. popup.html 文件内容
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Popup</title><style>*{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>
<body><header><h1>Popup</h1></header><main><button id="get_window_but">获取 window 数据</button><ul id="window_coverage"></ul></main>
</body>
<script src="popup.js"></script>
</html>
1.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 = `<div>url: ${e.message.location.href}</div><div>coverage: ${e.message.data ? JSON.stringify(e.message.data) : ''}</div>`coverageUl.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:按钮点击事件,发送消息到 SW
  • getCurrentTabId:获取当前活动的页面的 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 因为是在页面中,所以需要 tabId
    • popup 则不需要 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】
  • 🎉🎉🎉🎉🎉🎉

相关文章:

Chrome 浏览器插件获取网页 iframe 中的 window 对象

Chrome 浏览器插件获取网页 iframe 中的 window 对象 前言 之前写了篇《Chrome 浏览器插件获取网页 window 对象》文章&#xff0c;是获取当前页面的 window 对象&#xff0c;但是有些页面是嵌入 iframe 的&#xff0c;特别是系统项目主域一样&#xff0c;那就也需要获取 ifr…...

免费线上签字小程序,开启便捷电子签名

虽如今数字化飞速发展的时代&#xff0c;但线上签名小程序的开发制作却并非易事。需要攻克诸多技术难题&#xff0c;例如确保签名的真实性与唯一性&#xff0c;防止签名被伪造或篡改。 要精准地捕捉用户手写签名的笔迹特征&#xff0c;无论是笔画的粗细、轻重&#xff0c;还是…...

IT运维的365天--021 服务器上的dns设置后不起作用

之前在内网搭建了一个和外网同域名的网站&#xff0c;开发同事今天告诉我&#xff0c;程序调试发现可能服务器不能正常访问自己内网的网站内容。于是&#xff0c;今天的故事开始了。 前面的文章在下面列出&#xff0c;当然不看也问题不大&#xff0c;今天的主题是&#xff1a;…...

深信服企业级数据备份与恢复系统(整机裸机恢复)

概述 深信服企业级数据备份与恢复系统可实现无需搭建目标环境&#xff0c;目标机可以是没有操作系统的物理主机或虚拟机&#xff0c;实现异构环境下的裸机恢复。 深信服企业级数据备份与恢复系统支持的多种连接恢复方式&#xff1a; 1. PXE连接恢复&#xff1a;PXE连接需要做…...

Tool之Excalidraw:Excalidraw(开源的虚拟手绘风格白板)的简介、安装和使用方法、艾米莉应用之详细攻略

Tool之Excalidraw&#xff1a;Excalidraw(开源的虚拟手绘风格白板)的简介、安装和使用方法、艾米莉应用之详细攻略 目录 Excalidraw 简介 1、Excalidraw 的主要特点&#xff1a; Excalidraw 安装和使用方法 1、Excalidraw的安装 T1、使用 npm 安装&#xff1a; T2、使用 …...

OPPO C++面试题及参考答案

五层协议每层包含的协议 在计算机网络的五层协议体系结构&#xff08;自下而上为物理层、数据链路层、网络层、传输层和应用层&#xff09;中&#xff0c;各层包含多种协议。 物理层主要负责在物理介质上传输原始的比特流&#xff0c;包括像 RJ - 45 接口标准等物理接口规范&am…...

Unity中LineRenderer使用MeshCollider方法参考

运行时&#xff0c;如果一个物体不添加Collider组件就没有办法被鼠标点击&#xff0c;LineRenderer由于其Mesh会随着摄像机朝向变化&#xff0c;如果要通过添加MeshCollider来使其能够与鼠标交互&#xff0c;就需要不断同步更新其MeshCollider网格。 代码参考如下&#xff1a; …...

BERT模型入门(1)BERT的基本概念

文章目录 BERT是Bidirectional Encoder Representations from Transformers的首字母简写&#xff0c;中文意思是&#xff1a;Transformer的双向编码器表示。它是谷歌发布的最先进的嵌入模型。BERT在许多NLP任务中提供了更好的结果&#xff0c;如问答、文本生成、句子分类等&…...

致命错误: Class ‘ZipArchive‘ not found

银河麒麟V10处理 本人在安装过程遇到的坑&#xff0c;就是不要使用太低版本的 1、安装cmake 确认是否安装 cmake --version 如果没安装的话按照如下步骤处理下&#xff08;如果想要其他版本点击cmake官网下载&#xff09; wget https://github.com/Kitware/CMake/release…...

二手车交易平台开发:安全与效率的双重挑战

3.1系统体系结构 系统的体系结构非常重要&#xff0c;往往决定了系统的质量和生命周期。针对不同的系统可以采用不同的系统体系结构。本系统为二手车交易平台系统&#xff0c;属于开放式的平台&#xff0c;所以在体系结构中采用B/s。B/s结构抛弃了固定客户端要求&#xff0c;采…...

vector题目

118. 杨辉三角 - 力扣&#xff08;LeetCode&#xff09; 求解题目时候&#xff0c;我们可以将其看作近似的二维数组。 行为vector<vector<int>>,数组的每个数据类型为vector<int>。 列为vector<int>,数组的每个数据类型为int。 通过观察我们可以发现…...

测试测试测试测试测试测试测试测试测试测试

标题详情作者简介愚公搬代码头衔华为云特约编辑&#xff0c;华为云云享专家&#xff0c;华为开发者专家&#xff0c;华为产品云测专家&#xff0c;CSDN博客专家&#xff0c;CSDN商业化专家&#xff0c;阿里云专家博主&#xff0c;阿里云签约作者&#xff0c;腾讯云优秀博主&…...

Cisco WebEx 数据平台:统一 Trino、Pinot、Iceberg 及 Kyuubi,探索 Apache Doris 在 Cisco 的改造实践

导读&#xff1a;Cisco WebEx 早期数据平台采用了多系统架构&#xff08;包括 Trino、Pinot、Iceberg 、 Kyuubi 等&#xff09;&#xff0c;面临架构复杂、数据冗余存储、运维困难、资源利用率低、数据时效性差等问题。因此&#xff0c;引入 Apache Doris 替换了 Trino、Pinot…...

大恒相机开发(3)—大恒相机工业检测的实际案例

大恒相机工业检测的实际案例 工业检测的实际案例图像采集性能优化技巧工业环境下的稳定性 工业检测的实际案例 以下是一些使用大恒相机进行工业检测的实际案例&#xff1a; 多特征光学成像系统&#xff1a; 在这个案例中&#xff0c;使用大恒相机构建了一个全方位、多特征的图…...

【泛微表单】流程相关信息修改

流程相关信息修改 查询流程对应数据库表名: select b.tablename from workflow_bill b ,workflow_base s,workflow_requestbase t where t.requestid=35389 and t.workflowid = s.id and b...

LeetCode80.删除有序数组的重复项

10多分钟的时间就把一道中等题目做出来了&#xff0c;而且我还没有思考&#xff0c;边写边想。我的思路很简单&#xff0c;就是按照题目意思&#xff0c;从前往后遍历数组并统计相同的个数count&#xff0c;然后一直维护一个左指针&#xff0c;把遍历的数移到左指针上然后左指针…...

rk3568制冷项目驱动开发流程汇总(只适用于部分模块CIF DVP等,自用)

采用fpga输入&#xff0c;3568采集并显示至hdmi RKVICAP 驱动框架说明 RKVICAP驱动主要是基于 v4l2 / media 框架实现硬件的配置、中断处理、控制 buffer 轮转&#xff0c;以及控制 subdevice(如 mipi dphy 及 sensor) 的上下电等功能。 对于RK356X 芯片而言&#xff0c; VICAP…...

费舍尔信息矩阵全面讲述

费舍尔信息矩阵&#xff08;Fisher Information Matrix&#xff09; 费舍尔信息矩阵是统计学中一个非常重要的概念&#xff0c;尤其在参数估计、最大似然估计&#xff08;MLE&#xff09;和贝叶斯推断中具有广泛的应用。它反映了参数估计的不确定性程度&#xff0c;也可以用来…...

DALFox-一款XSS自动化扫描工具

声明&#xff01;本文章所有的工具分享仅仅只是供大家学习交流为主&#xff0c;切勿用于非法用途&#xff0c;如有任何触犯法律的行为&#xff0c;均与本人及团队无关&#xff01;&#xff01;&#xff01; 目录标题 一、介绍及使用启动及使用1. 单个扫描2. 多个扫描3. 文件扫描…...

Python 异步协程:从 async/await 到 asyncio 再到 async with

在 Python 3.8 以后的版本中&#xff0c;异步编程变得越来越重要。本文将系统介绍 Python 标准库中的异步编程工具&#xff0c;带领大家掌握 async/await 语法和 asyncio 的使用。 从一个简单的场景开始 假设我们在处理一些耗时的 I/O 操作&#xff0c;比如读取多个文件或处理…...

逻辑回归:给不确定性划界的分类大师

想象你是一名医生。面对患者的检查报告&#xff08;肿瘤大小、血液指标&#xff09;&#xff0c;你需要做出一个**决定性判断**&#xff1a;恶性还是良性&#xff1f;这种“非黑即白”的抉择&#xff0c;正是**逻辑回归&#xff08;Logistic Regression&#xff09;** 的战场&a…...

大型活动交通拥堵治理的视觉算法应用

大型活动下智慧交通的视觉分析应用 一、背景与挑战 大型活动&#xff08;如演唱会、马拉松赛事、高考中考等&#xff09;期间&#xff0c;城市交通面临瞬时人流车流激增、传统摄像头模糊、交通拥堵识别滞后等问题。以演唱会为例&#xff0c;暖城商圈曾因观众集中离场导致周边…...

Linux简单的操作

ls ls 查看当前目录 ll 查看详细内容 ls -a 查看所有的内容 ls --help 查看方法文档 pwd pwd 查看当前路径 cd cd 转路径 cd .. 转上一级路径 cd 名 转换路径 …...

MODBUS TCP转CANopen 技术赋能高效协同作业

在现代工业自动化领域&#xff0c;MODBUS TCP和CANopen两种通讯协议因其稳定性和高效性被广泛应用于各种设备和系统中。而随着科技的不断进步&#xff0c;这两种通讯协议也正在被逐步融合&#xff0c;形成了一种新型的通讯方式——开疆智能MODBUS TCP转CANopen网关KJ-TCPC-CANP…...

【决胜公务员考试】求职OMG——见面课测验1

2025最新版&#xff01;&#xff01;&#xff01;6.8截至答题&#xff0c;大家注意呀&#xff01; 博主码字不易点个关注吧,祝期末顺利~~ 1.单选题(2分) 下列说法错误的是:&#xff08; B &#xff09; A.选调生属于公务员系统 B.公务员属于事业编 C.选调生有基层锻炼的要求 D…...

NFT模式:数字资产确权与链游经济系统构建

NFT模式&#xff1a;数字资产确权与链游经济系统构建 ——从技术架构到可持续生态的范式革命 一、确权技术革新&#xff1a;构建可信数字资产基石 1. 区块链底层架构的进化 跨链互操作协议&#xff1a;基于LayerZero协议实现以太坊、Solana等公链资产互通&#xff0c;通过零知…...

大语言模型(LLM)中的KV缓存压缩与动态稀疏注意力机制设计

随着大语言模型&#xff08;LLM&#xff09;参数规模的增长&#xff0c;推理阶段的内存占用和计算复杂度成为核心挑战。传统注意力机制的计算复杂度随序列长度呈二次方增长&#xff0c;而KV缓存的内存消耗可能高达数十GB&#xff08;例如Llama2-7B处理100K token时需50GB内存&a…...

在QWebEngineView上实现鼠标、触摸等事件捕获的解决方案

这个问题我看其他博主也写了&#xff0c;要么要会员、要么写的乱七八糟。这里我整理一下&#xff0c;把问题说清楚并且给出代码&#xff0c;拿去用就行&#xff0c;照着葫芦画瓢。 问题 在继承QWebEngineView后&#xff0c;重写mousePressEvent或event函数无法捕获鼠标按下事…...

C++:多态机制详解

目录 一. 多态的概念 1.静态多态&#xff08;编译时多态&#xff09; 二.动态多态的定义及实现 1.多态的构成条件 2.虚函数 3.虚函数的重写/覆盖 4.虚函数重写的一些其他问题 1&#xff09;.协变 2&#xff09;.析构函数的重写 5.override 和 final关键字 1&#…...

安全突围:重塑内生安全体系:齐向东在2025年BCS大会的演讲

文章目录 前言第一部分&#xff1a;体系力量是突围之钥第一重困境是体系思想落地不畅。第二重困境是大小体系融合瓶颈。第三重困境是“小体系”运营梗阻。 第二部分&#xff1a;体系矛盾是突围之障一是数据孤岛的障碍。二是投入不足的障碍。三是新旧兼容难的障碍。 第三部分&am…...