大家好,我是 dom 哥。这是我关于 Chrome 扩展开发的系列文章,感兴趣的可以 点个小星星

一个复杂的 Chrome 扩展程序通常由 content_scriptsbackgroundaction popupside paneloptions pagedevtools 等部分组成,这些部分所负责的功能各不相同,所处的运行环境各不相同,所能访问的 chrome.* API 也各不相同,也因此经常需要通信告诉对方需要做什么。

下面是我画的一张图,简单说明各部分关系:

这些花花绿绿的部分各自运行在不同的环境中,往往需要相互通信,Chrome 为我们提供了两种通信方式:

  • 一种是一次性请求(one-time requests),一次只能发一条消息,类似于手机发短信,跟 HTTP 请求很像。
  • 一种是长期连接(long-lived connections),允许发送多条消息,类似于手机打电话,跟 Websocket 连接很像。

接下来就详细说说这两种通信方式。

一次性请求(one-time requests)

如果要向扩展程序的另一部分发送一条消息,有两个 API 可供调用:

  • chrome.runtime.sendMessage(extensionId?, message)
  • chrome.tabs.sendMessage(tabId, message)

从函数签名很容易看出来,一个是向扩展程序的各个部分发消息的,另一个是给某个浏览器的某个页签发消息的。

为什么设计两个 API?这是因为 content_scripts 是一个很独特的存在!

先说说浏览器的的工作原理。

浏览器的每个页签都是单独的线程。每个页签运行在与其他页签或扩展相隔离的独立线程中。如下图所示

我们在每个页签中打开页面。content_scripts 是一个很特殊的存在!作为被注入到页面的脚本,它的生命周期跟随页面。而扩展程序的其他部分,都有自己的生命周期!如果你在各个部分查看它们的 location,就会发现,只有 content_scripts 的 origin 是页面的 url 一样,而其它部分的 location.origin 都是 chrome://your-extention-id

知道了 content_scripts 的特殊性后,那么这两个 API 就很好理解了。

chrome.runtime.sendMessage() 是给扩展程序发消息的,它的第一个参数是一个可选的 extensionId,意味着不但可以给自身扩展程序发消息,还能给别的扩展程序发消息,它发送的消息可以被扩展的任一部分接收到,包括 backgroundaction popupside paneloptions pagedevtools 等等,除了 content_scripts!!!

那么想给 content_scripts 发送消息怎么办呢???

chrome.tabs.sendMessage() 就是专门用来给 content_scripts 发消息的!值得注意的是,想要给 content_scripts 发消息需要指定 tabId,也就是需要指明给哪个页签下的页面的 content_scripts 发消息。这个设计很好,因为每个页签的页面都运行了一份 content_scripts,这就避免了无关的页面接收到消息。

发送消息搞定啦,有方法发送就得有方法接收才行啊。

接收消息的方法只有一个 API:

chrome.runtime.onMessage.addListener(
(message, sender, sendResponse) => boolean | undefined
)

在扩展程序的任意部分(包括 content_scripts)都是用这个接收消息。这很方便。

长期连接(long-lived connections)

长期链接的 API 和一次性消息的 API 是相互对应的。

要创建一个可重复使用的长期消息传递通道,有两个 API 可以调用:

  • chrome.runtime.connect(extensionId?, connectInfo?): Port
  • chrome.tabs.connect(tabId, connectInfo?): Port

这两个 API 的设计和一次性消息的一样。

chrome.runtime.connect() 用于和扩展程序的任一部分建立消息通道,除了 content_scripts!!!

chrome.tabs.connect() 是专门用来和 content_scripts 建立消息通道哒!

chrome.{runtime,tabs}.connect() 返回的是一个 Port 对象。Port 就是被设计用来在扩展程序的不同部分之间进行双向通信的一个接口。

觉得不错可以 点个小星星 支持一下哦

Chrome扩展程序是如何进行消息传递的的更多相关文章

  1. 【前端工具】Chrome 扩展程序的开发与发布 -- 手把手教你开发扩展程序

    关于 chrome 扩展的文章,很久之前也写过一篇.清除页面广告?身为前端,自己做一款简易的chrome扩展吧. 本篇文章重在分享一些制作扩展的过程中比较重要的知识及难点. 什么是 chrome 扩展 ...

  2. ----转载----【前端工具】Chrome 扩展程序的开发与发布 -- 手把手教你开发扩展程序

    关于 chrome 扩展的文章,很久之前也写过一篇.清除页面广告?身为前端,自己做一款简易的chrome扩展吧. 本篇文章重在分享一些制作扩展的过程中比较重要的知识及难点. 什么是 chrome 扩展 ...

  3. chrome扩展程序开发

    首先,明确两个概念的区别:chrome扩展程序和Web Apps.具体参考:http://www.chromi.org/archives/10106 本文只讨论chrome扩展程序. 最好的开发教程莫 ...

  4. 编写Chrome扩展程序

    Chrome的扩展程序很多,也很容易入门,可以来简单实现一下 看看,慢慢就能实现出一个扩展程序来 每个扩展程序应用一般会包含: 一个manifest清单文件 html文件 js文件 其他文件等 可以看 ...

  5. Web 开发人员必备的12款 Chrome 扩展程序

    之前已经分享过一些帮助 Web 开发人员和设计师的 Chrome 扩展,这次我们继续展示一组很有用的 Chrome 应用程序.这些免费的 Chrome 应用程序可以简化您的工作流程,为了加快您的工作流 ...

  6. Google Chrome 扩展程序开发

    根据公司的规定,每月八小时,弹性工作制.所以大家平时来的不太准时,如果有事,下班也就早些回去了.所以一个月下来工作时间可能不够,但是公司的考勤日历是这样的: 除了请假和法定节假日外,其他样式显示都是一 ...

  7. 解决高版本 Google Chrome 扩展程序强制停用问题 -摘自网络

    1]前往这里下载你喜欢的语言的组策略模板 后缀为.adm (其他的文件自己看 https://docs.google.com/viewer?a=v&pid=sites&srcid=Y2 ...

  8. 【转】编写Chrome扩展程序

    Chrome的扩展程序很多,也很容易入门,可以来简单实现一下 看看,慢慢就能实现出一个扩展程序来 每个扩展程序应用一般会包含: 一个manifest清单文件 html文件 js文件 其他文件等 可以看 ...

  9. Chrome扩展程序——TabCopy:一键复制网页标题和网址

    Chrome扩展程序——TabCopy:一键复制网页标题和网址 - Erik_ly的博客 - CSDN博客 https://blog.csdn.net/u012318074/article/detai ...

  10. 如何用原生js开发一个Chrome扩展程序

    原文地址:How to Build a Simple Chrome Extension in Vanilla JavaScript 开发一个Chrome扩展程序非常简单,只需要使用原生的js就可以完成 ...

随机推荐

  1. excel的烦恼

    Smiling & Weeping ---- 他未对我好半分,偏巧这感情疯长似野草 题目链接:https://www.matiji.net 思路:与新三进制2思路相似,转化为纯26进制,然后往 ...

  2. Codeforces Round 882 div.2 B

    Smiling & Weeping ----玫瑰花你拿才好看,风景要和你看才浪漫--<-<-<@ B. Hamon Odyssey time limit per test 1 ...

  3. dedebiz实时时间调用

    {dede:tagname runphp='yes'}@me = date("Y-m-d H:i:s", time());{/dede:tagname}

  4. 每日一题:如何判断是否是数组,一个既简单又复杂的问题。(不要再用Object.prototype.toString.call、instance of判断了!!!)

    1.不要使用Object.prototype.toString.call() 正常情况下: const arr = [1,2,3,4,5] const obj = {} console.log(Obj ...

  5. MySQL 日志管理、备份与恢复

    MySQL 日志管理.备份与恢复 ---MySQL 日志管理--- MySQL 的日志默认保存位置为 /usr/local/mysql/data vim /etc/my.cnf [mysqld] ## ...

  6. Modbus转profinet网关连接1200PLC在博图组态与英威腾驱动器通讯程序案例

    Modbus 转 profinet 网关连接 1200PLC 在博图组态与英威腾驱动器通讯程序案例 本案例给大家介绍由兴达易控 modbus 转 profinet 网关连接 1200PLC 在博图软件 ...

  7. E-GraphSAGE: A Graph Neural Network based Intrusion Detection System 笔记

    E-GraphSAGE: A Graph Neural Network based Intrusion Detection System 目录 E-GraphSAGE: A Graph Neural ...

  8. redis 源码分析:Jedis 哨兵模式连接原理

    1. 可以从单元测试开始入手 查看类JedisSentinelPool private static final String MASTER_NAME = "mymaster"; ...

  9. 前端设计模式:工厂模式(Factory)

    00.基础概念 工厂模式封装了对象的创建new(),将消费者(使用)和生产者(实现)解耦. 工厂是干什么的?工厂是生产标准规格的商品的地方,建好工厂,投入原料(参数),产出特定规格的产品.so,工厂模 ...

  10. IDEA在Debug模式下修改Java类,不小心关闭 Reload Changed Classes for AppArrowWebApplication 框提示之后的处理

    问题描述:Springboot maven 聚合项目里面,经常要启动多个服务. 当我们修改其中一个服务的时候,debug 启动时 idea 就会提示是否需要重新编译修改的内容,弹窗让你选择reload ...