开发谷歌插件

本文详细介绍了谷歌插件的开发过程,包括manifest.json的配置、调试方法以及popup与content-script间的消息通信。在消息通信中,重点解决了异步响应和Blob数据传输的问题。此外,还分享了在遇到困难时如何克服,强调实践并不像想象中那么难。
摘要由CSDN通过智能技术生成

入门谷歌插件

一个谷歌扩展其实就是一个配置(入口)文件 manifest.json 和一系列 html、css、js、图片文件的集合

  • manifest.json 说明
{
  // 插件的名称
  "name": "测试插件",
  // 插件的描述
  "description": "april的谷歌插件",
  "version": 0.1,
  "manifest_version": 2,
  // 图标位置
  "icons": {
    "19": "icons/icon19.png",
    "38": "icons/icon38.png",
    "48": "icons/icon48.png",
    "128": "icons/icon128.png"
  },
  // 设置扩展的图标放在 Chrome 工具栏中
  "browser_action": {
    "default_title": "april",
    // 点击扩展图标所显示的页面位置
    "default_popup": "popup/popup.html"
  },
  // 可以使拓展常驻后台,比较常用的是指定子属性scripts,表示在拓展启动时自动创建一个包含所有指定脚本的页面。
  "background": {
    "scripts": [
      "background.js"
    ]
  },
  // 定义拓展需要向chorme申请的权限
  "permissions": [
    // 可以跨域请求的接口
    "https://www.baidu.com/",
    // 存储
    "storage",
    // 浏览器选项卡
    "tabs",
    // 当前活动选项卡
    "activeTab",
    // 浏览器通知
    "notifications",
    // 右键菜单
    "contextMenus",
  ],
  // 自定义页面替换chrome相应的页面,新标签页(newTab)、书签页面(bookmarks)、历史记录(history)
  "chrome_url_overrides": {
        "newtab": "tab.html"
   },
   // 需要直接注入页面的JS
  "content_scripts": [
    {
      // 匹配的URL,<all_urls>表示匹配所有
      "matches": [
        "<all_urls>"
      ],
      "js": [
        "content-script.js"
      ],
      // 通过插件向页面中注入脚本。content-scripts 和原始页面共享 DOM,但是不共享JS。代码注入的时间,可选值: "document_start", "document_end", or "document_idle",最后一个表示页面空闲时,默认document_idle
      "run_at": "document_start"
    }
  ]
}
}
  • 调试
├── images/
├── popup.html
├── manifest.json
├── content-script.js

打开拓展页面(chrome://extensions/),打开开发者模式,点击如图 加载正在开发的扩展程序,选择你的文件夹,就可以看到了。每次更改配置文件之后,都需要点击刷新按钮重新加载。

在这里插入图片描述

遇到的主要问题

  • 消息通信
    popup 向 content 互相通信

popup.js

// 向content-script发送信息
function sendMessageToContentScript(message, callback) {
    getCurrentTabId((tab) => {
        // 在参数中添加当前页面的URL
        chrome.tabs.sendMessage(tab.id, { ...message, url: tab.url }, function(response) {
            if (callback) callback(response)
        })
    })
},
// 获取当前选项卡ID
function getCurrentTabId(callback) {
    chrome.tabs.query({ active: true, currentWindow: true }, function(tabs) {
        if (callback) callback(tabs.length ? tabs[0] : null)
    })
}
// 测试通讯事件
document.getElementById('getSume').onclick = function() {
    sendMessageToContentScript({ cmd: 'update_font_size', size: 42 }, function(response) {
        // response就是content-script发过来的消息
        alert(response)
    })
}

content-script.js

// 接收来自后台的消息
chrome.runtime.onMessage.addListener(function(request, sender, sendResponse) {
    console.log(
        '收到来自 ' + (sender.tab ? 'content-script(' + sender.tab.url + ')' : 'popup或者background') + ' 的消息:',
        request
    )
    sendResponse('我收到你的消息了:' + JSON.stringify(request))
})
  • 带有异步的 chrome.runtime.onMessage 响应

错误的代码,传到 popup.js 中一直获取的是 undefined

chrome.runtime.onMessage.addListener(async (request, sender, sendResponse) => {
    let key = await getKey()
    sendResponse(key)
})

解决:

chrome.runtime.onMessage.addListener(function (request, sender, sendResponse) => {
    (async () => {
        let key = await getKey()
        sendResponse(key)
    })()
    return true
})
  • content-script.js 向 popup 传递 Blob 类型数据
    问题:在传参为 Blob 类型,在 content-script.js 打印出来没问题,但传给后端就变成了[object object]。如图所示:

    打印的blob

在这里插入图片描述

解决:
谷歌扩展只能传输和 JSON 兼容的数据,可通过 JSON.parse(JSON.stringify(form_data))判断兼容与否。

在这里插入图片描述

Blob 和 JSON 不兼容。要上传文件,可通过发送方将 Blob 对象转换为 dataURL,接收方解析回 Blob 对象,再生成 FormData 对象上传文件

发送方:

```js
let file = null
let reader = new FileReader()
// 将blob转换为dataURL
reader.readAsDataURL(data)
reader.onload = function(e) {
    file = e.target.result
    sendResponse({
        file,
    })
}
```

接收方:

```js
this.sendMessageToContentScript(item, async function(response) {
    // dataURL转换为Blob
    const dataURLtoBlob = (dataUrl) => {
        let arr = dataUrl.split(','),
            mime = arr[0].match(/:(.*?);/)[1],
            bstr = atob(arr[1]),
            n = bstr.length,
            u8arr = new Uint8Array(n)
        while (n--) {
            u8arr[n] = bstr.charCodeAt(n)
        }
        return new Blob([u8arr], {
            type: mime,
        })
    }
    const { file } = response

    let formData = new FormData()
    formData.append('file', dataURLtoBlob(file))
    let { data } = await axios.post('XXX', formData, {
        headers: {
            'Content-Type': 'application/x-www-form-urlencoded;charset=utf-8',
        },
    })
})
```

— 接到需求的时候,觉得自己搞不定,了解一番之后也没有想象的那么难~完

在这里插入图片描述

参考文章:

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值