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

Chrome 浏览器插件获取网页 window 对象(方案一)

前言

最近有个需求,是在浏览器插件中获取 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.

一、两个 JS 文件,通过 postMessage 传递消息

1. 方案思路

  1. 新建两个 js 文件,index.jslucky.js
  2. content_scripts 中嵌入 index.js 文件
  3. index.js 中通过 script 标签,嵌入 lucky.js
  4. index.js 中通过 window.addEventListener('message') 监听消息
  5. lucky.js 中通过 window.postMessage 进行消息传递
  6. manifest.json 文件中添加 web_accessible_resources
1.1. 方案流程

流程图如下:

画板

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
const init = () => {
  const script = document.createElement('script')
  script.src = chrome.runtime.getURL('lucky.js')
  document.head.appendChild(script)

  // 监听从页面上下文发回的消息
  window.addEventListener('message', (event) => {
    console.log('event', event)
    if (event.source !== window) return
    if (event.data.type === 'get-window-data') {
      console.log('window data:', event.data.data)
    }
  })
}

// 判断 window.top 和 self 是否相等,如果不相等,则不注入
if (window.top == window.self) {
  init()
}
3.2. lucky.js
window.postMessage({
  type: 'get-window-data',
  data: window.MyBlog,
  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": [
        "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": [
    {
      "resources": ["lucky.js"],
      "matches": ["http://localhost:*/*"],
      "use_dynamic_url": true
    }
  ]
}
3.4. 项目文件结构
.
├── index.html
├── index.js
├── lucky.js
├── manifest.json
└── service-worker.js
3.5. 方案效果

在控制台中选择当前插件,即可查看获取的 window 下的 MyBlog 对象

在这里插入图片描述

4. 动态获取参数

如果想通过点击等操作获取数据,则方法如下

4.1. 实现流程

如果想通过页面按钮点击再获取数据,也是通过 postMessage 发送消息,以及通过 addEventListener 接收消息再次发送到插件

流程图如下:

画板

4.2. 实现代码
4.2.1. index.js
/**
 * 发送消息
 * @param {string} type 类型
 * @param {string} field 获取的字段名称
 */
const postMessage = (type, field) => {
  window.postMessage({
    type,
    field,
    file: 'index'
  })
}
/**
 * 初始化
 */
const init = () => {
  const script = document.createElement('script')
  script.src = chrome.runtime.getURL('lucky.js')
  document.head.appendChild(script)

  // 监听从页面上下文发回的消息
  window.addEventListener('message', (event) => {
    console.log('event', event)
    if (event.source !== window) return
    if (event.data.type === 'get-window-data') {
      console.log('window data:', event.data.data)
    }
  })

  // 加入定时器是因为 lucky.js 加载需要时间,如果不需要初始化就获取数据,可以把这行删除
  // 如果想初始化就获取数据,又不想加 setTimeout,就把下面 lucky.js 注释的代码放开就行
  setTimeout(() => postMessage('get-window-field', 'MyBlog'), 100)
  
  // 或者在 script onload 的时候进行消息发送
  // script.onload = () => {
  //   postMessage('get-window-field', 'MyBlog')
  // }

  // 插入 button 按钮
  const button = document.createElement('button')
  button.innerText = '获取数据'
  button.id = 'chrome-ext-but'
  document.body.appendChild(button)
  button.onclick = () => {
    postMessage('get-window-field', 'MyBlog')
  }
}

// 判断 window.top 和 self 是否相等,如果不相等,则不注入
if (window.top == window.self) {
  init()
}
4.2.2. 点击按钮获取数据

4.2.3. lucky.js
// 如果想初始化就传递消息,也不想加 setTimeout,则放开下面的代码
// window.postMessage({
//   type: 'get-window-data',
//   data: window.MyBlog,
//   file: 'lucky'
// })

/**
 * 监听 message 消息
 */
window.addEventListener('message', (event) => {
  if (event.data?.type === 'get-window-field') {
    window.postMessage({
      type: 'get-window-data',
      data: window[event.data.field],
      file: 'lucky'
    })
  }
})

5. 代码地址

  • 【Gitee】
  • 【Github】

参考

  • 【postMessage】
  • 【Content_script】

http://www.kler.cn/a/289952.html

相关文章:

  • 设计模式之装饰器模式(SSO单点登录功能扩展,增加拦截用户访问方法范围场景)
  • 认识一下Unicorn
  • 深度学习中的感受野:从基础概念到多层次特征提取
  • 【121. 买卖股票的最佳时机】——贪心算法/动态规划
  • DataWorks on EMR StarRocks,打造标准湖仓新范式
  • Unity3D实现视频和模型融合效果
  • pip切换清华源
  • 数据结构二叉树——堆
  • Scott Brinker:Martech中的AI会让买家体验更好还是更糟?这取决于…….
  • Unity版本升级2022 Gradle 升级7.x版本调整
  • 代码随想录 刷题记录-27 图论 (4)拓扑排序
  • Rides实现分布式锁,保障数据一致性,Redisson分布式事务处理
  • python学习之路 - PySpark快速入门
  • docker实战基础三(Docker基础命令)
  • lvgl 自定义组件介绍二
  • yolo训练策略--使用 Python 和 OpenCV 进行图像亮度增强与批量文件复制之(图像增强是按梯度变化优化)
  • 光盘安全隔离与信息单向导入系统-信刻
  • 以人口金字塔图为例,在线绘制左右双侧堆叠条形图
  • 如何设计店铺租赁租凭平台?Java SpringBoot实现全攻略
  • 后端是否开启异步执行,看打印日志的线程信息
  • 多线程篇(可见性 原子性 有序性(原子性))(持续更新迭代)
  • 09J621-2《电动采光排烟天窗》技术详解
  • openharmony历程一:安装ubuntu20.04
  • Vue基础语法
  • ai聊天软件哪个好用?分享5款实用的智能聊天软件
  • Linux云计算学习笔记11 (计划任务)