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 字段

javascript 复制代码
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
javascript 复制代码
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
javascript 复制代码
window.postMessage({
  type: 'get-window-data',
  data: window.MyBlog,
  file: 'lucky'
})
3.3. manifest.json
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. 项目文件结构
shell 复制代码
.
├── 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
javascript 复制代码
/**
 * 发送消息
 * @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
javascript 复制代码
// 如果想初始化就传递消息,也不想加 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. 代码地址

参考

相关推荐
[seven]3 分钟前
React Router TypeScript 路由详解:嵌套路由与导航钩子进阶指南
前端·react.js·typescript
无我Code21 分钟前
前端-2025年末个人总结
前端·年终总结
文刀竹肃38 分钟前
DVWA -SQL Injection-通关教程-完结
前端·数据库·sql·安全·网络安全·oracle
LYFlied43 分钟前
【每日算法】LeetCode 84. 柱状图中最大的矩形
前端·算法·leetcode·面试·职场和发展
Bigger1 小时前
Tauri(21)——窗口缩放后的”失焦惊魂”,游戏控制权丢失了
前端·macos·app
Bigger1 小时前
Tauri (20)——为什么 NSPanel 窗口不能用官方 API 全屏?
前端·macos·app
bug总结1 小时前
前端开发中为什么要使用 URL().origin 提取接口根地址
开发语言·前端·javascript·vue.js·html
一招定胜负2 小时前
网络爬虫(第三部)
前端·javascript·爬虫
Shaneyxs2 小时前
从 0 到 1 实现CloudBase云开发 + 低代码全栈开发活动管理小程序(13)
前端
半山烟雨半山青2 小时前
微信内容emoji表情包编辑器 + vue3 + ts + WrchatEmogi Editor
前端·javascript·vue.js