谷歌插件开发:Message Passing API 详解(手把手带你从零探索开发谷歌插件)

我正在参加「掘金·启航计划」

本节将深入介绍 Google Chrome 插件的进阶特性之一:Message Passing API。通过详细讲解 Message Passing API 的概念、作用和运行方式,您将能够理解插件间的消息传递机制,并学会如何在插件中实现跨页面通信和数据交换。通过深入学习 Message Passing API,您可以为插件开发增加更多的功能和交互性,提升用户体验。


课程目录(暂定18节)

后续可持续关注此贴,目录路径都会补上,点击即可跳转前往

  1. 序章:拓展技术池,一起来探索谷歌插件吧!
  2. 插件结构:manifest.json 配置文件详解
  3. 实战开发:创建自己的第一个Google插件
  4. 插件结构:background.js 文件详解
  5. 进阶高级:Browser Action API 详解
  6. 进阶高级:Tabs Manager API 详解
  7. 谷歌插件开发:content.js 文件详解
  8. 谷歌插件开发:Content Script API 详解
  9. 谷歌插件开发:Message Passing API 详解
  10. 进阶高级:Storage API 详解
  11. 进阶高级:File System Access API 详解
  12. 进阶高级:XMLHttpRequest 详解
  13. 进阶高级:Bookmarks API 详解
  14. 进阶高级:Downloads API 详解
  15. 进阶高级:如何使用vue来开发一款Google插件
  16. 实战开发:从零开发一款企业级Google插件(上)
  17. 实战开发:从零开发一款企业级Google插件(下)
  18. 收官之作:总结与展望

一. 基本介绍

在开发 Google Chrome 插件时,经常会遇到需要不同插件页面之间进行通信和数据传递的情况。为了实现这种跨页面的交互,Chrome 提供了 Message Passing API。Message Passing API 允许插件的不同部分之间安全地发送消息和共享数据,实现了插件的高度灵活性和可扩展性。

Message Passing API 是 Chrome 插件提供的一种机制,可以让不同的插件组件之间进行通信。通过该 API,插件的不同组件(如 background page、content script、popup 窗口等)可以互相发送消息和接收消息,以实现数据传递和功能调用等操作。

在 Message Passing API 中,消息的发送和接收是基于异步的事件驱动模型,即发送方通过 API 发送消息,接收方通过注册事件监听器来接收消息。当消息被发送时,接收方会触发监听器并执行相应的操作。

作用

它的基本原理是通过发送和接收消息来实现通信。插件中的不同部分可以使用 API 提供的方法发送消息,并在接收方注册监听器以接收消息。消息可以是简单的文本、JSON 对象或包含更复杂数据结构的信息。

在实际开发场景中,我们可以使用 Message Passing API 来实现以下功能,例如:

  1. 插件的不同组件之间的通信: 它可以让插件的不同组件之间进行通信,包括 background page、content script、popup 窗口等。
  2. 插件和网页之间的通信: 通过 Message Passing API,插件可以和网页之间进行通信,实现数据传递和功能调用等操作。
  3. 插件和服务器之间的通信: 通过 Message Passing API,插件可以和服务器之间进行通信,实现数据传递和功能调用等操作。
  4. 插件和其他插件之间的通信: 通过 Message Passing API,插件可以和其他插件之间进行通信,实现数据传递和功能调用等操作。

Message Passing API 的作用在于帮助Chrome插件不同组件之间进行协作,以实现更强大的功能。例如,后台页面可以监听用户操作,同时控制着弹出窗口的显示和隐藏;弹出窗口可以向后台页面发送请求,获取数据并更新UI;内容脚本可以与当前打开的网页交互,获取或修改页面上的元素等。

运行方式

Message Passing API 的运行方式涉及两个主要的角色:发送方和接收方。下面将介绍它们的运行方式和交互流程。

  1. 发送消息:
    • 在发送方页面中,使用 chrome.runtime.sendMessage() 方法发送消息。该方法接受三个参数:目标插件的标识符、要发送的消息和一个可选的回调函数。
    • 消息可以是简单的文本或包含更复杂数据结构的 JSON 对象。
  1. 接收消息:
    • 在接收方页面中,通过注册消息监听器来接收消息。使用 chrome.runtime.onMessage 方法注册监听器,并定义一个回调函数来处理接收到的消息。
    • 监听器可以注册在后台页面、内容脚本和其他插件页面。
  1. 跨页面通信:
    • 插件页面之间的消息传递可以通过指定目标插件的标识符来实现。可以使用 chrome.runtime.connect() 方法建立插件页面之间的长连接,并通过连接对象发送和接收消息。
  1. 错误处理和回调:
    • 当发送消息时,可以提供一个可选的回调函数来处理发送操作的结果。
    • 在接收消息时,可以选择返回一个结果给发送方,通过回调函数获取接收操作的结果。

需要注意的事项 ⚠️

  1. API 的参数和返回值必须是可序列化的数据类型,如字符串、数字、布尔值等。
  2. 消息传递过程中,需要对数据进行编码和解码,以保证数据的完整性和正确性。
  3. 由于消息传递是异步的,因此需要使用回调函数来处理返回值。
  4. 由于插件的不同组件之间是通过消息传递进行通信的,因此需要注意消息的发送和接收的时序关系,以避免出现数据丢失或不一致的情况。
  5. 在使用 Message Passing API 时,需要谨慎处理数据的安全性,避免恶意代码对插件进行攻击。

Message Passing API 主要提供了以下内容 :

字段名 描述
chrome.runtime.sendMessage() 用于向指定的扩展程序或 content script 发送消息
chrome.runtime.onMessage() 用于监听来自指定的扩展程序或 content script 发送的消息
chrome.runtime.connect() 用于在扩展程序或 content script 之间建立长连接,以便进行双向通信
chrome.runtime.onConnect() 用于监听来自扩展程序或 content script 建立的连接请求,并返回连接对象以便进行通信

二. 主要方法

1. chrome.runtime.sendMessage()

chrome.runtime.sendMessage()用于向插件的后台页面发送消息,并接收响应,它的作用是将消息发送到插件的后台页面,并等待后台页面的响应。在发送消息时,我们可以传递一个包含要发送数据的JavaScript对象,而在接收响应时,则需要提供一个回调函数来处理返回的数据。

在Google插件开发中,我们通常需要从Content Script中向后台页面发送请求或获取数据,并根据返回值来进行相应的处理。此时,chrome.runtime.sendMessage方法就可以派上用场了。

它共有三个参数:

字段名 描述
message 要发送的消息内容,可以是任何JavaScript对象
responseCallback 接收响应的回调函数,该函数会在后台页面返回响应时被调用,可以访问后台页面返回的任何JavaScript对象
options 可选参数,用于指定消息发送的目标(例如,指定插件ID)和其他设置

需要注意的是,由于Content Script与后台页面运行在不同的JavaScript环境中,因此它们之间无法直接共享变量和函数。如果需要在Content Script和后台页面之间传递数据,可以使用JSON序列化、解析或者Chrome扩展的原生消息格式来进行数据传输。

下面是一个使用chrome.runtime.sendMessage方法向后台页面发送消息的示例代码:

// 向后台页面发送消息,请求获取设置信息
chrome.runtime.sendMessage({action: 'getSettings'}, function(response) {
  console.log('获取到的设置信息为:', response);
});

该示例代码中,首先使用chrome.runtime.sendMessage方法向后台页面发送一个JavaScript对象{action: 'getSettings'}作为请求参数,然后在回调函数中接收后台页面返回的响应数据response并输出到控制台。

2. chrome.runtime.onMessage()

chrome.runtime.onMessage 是 Message Passing API 中用于监听来自其他扩展程序或 content script 发送的消息的事件。

具体来说,当其他扩展程序或 content script 调用 chrome.runtime.sendMessage() 发送消息时,可以通过监听 chrome.runtime.onMessage 事件来接收到这些消息。当收到消息后,可以根据消息的内容执行相应的操作,例如修改页面内容、向页面注入脚本等。

它共有三个参数:

字段名 描述
callback 接收到消息时的回调函数,必选参数
options 消息接收选项,可选参数
responseCallback 发送响应消息时的回调函数,可选参数。如果不传递该参数,则收到消息后不发送响应

以下是一个简单的代码示例,演示了如何在 content script 中监听 chrome.runtime.onMessage 事件,接收来自 popup 的消息并执行相应的操作:

// content_script.js

// 监听来自其他扩展程序或 content script 发送的消息
chrome.runtime.onMessage.addListener(function(request, sender, sendResponse) {
  // 根据消息内容执行相应的操作
  if (request.action === 'modifyPageContent') {
    document.body.style.backgroundColor = 'pink';
    sendResponse({ message: 'Page content modified!' });
  }
});

在上面的代码中,我们在 content script 中注册了 chrome.runtime.onMessage 事件的监听器,当收到 chrome.runtime.sendMessage() 发送过来的消息时,会执行回调函数。在回调函数中,我们判断消息内容的 action 属性,如果是 'modifyPageContent',则将页面的背景色修改为粉色,并通过 sendResponse 方法向消息发送方返回响应消息,内容为 { message: 'Page content modified!' }

需要注意的事项 ⚠️

  1. 在监听 chrome.runtime.onMessage 事件时,需要使用 chrome.runtime.onMessage.addListener() 方法注册监听器。
  2. 在回调函数中,可以通过 request 参数获取到消息的内容,通过 sender 参数获取到消息发送方的信息,通过 sendResponse 方法向消息发送方返回响应消息。
  3. 当使用 sendResponse 方法向消息发送方返回响应消息时,需要保证回调函数返回 true 值,否则消息发送方可能无法接收到响应消息。
  4. 当使用 chrome.runtime.sendMessage() 发送消息时,需要注意消息的格式,只支持序列化的对象类型。
  5. 在 content script 中,需要在 manifest.json 文件中声明相应的权限,才能与其他扩展程序或页面进行通信。例如:
{
  "name": "My Extension",
  "version": "1.0",
  "manifest_version": 3,
  "permissions": [
    "tabs",
    "activeTab",
    "scripting",
    "<all_urls>"
  ],
  "content_scripts": [
    {
      "matches": ["<all_urls>"],
      "js": ["content_script.js"]
    }
  ]
}

在上面的示例中,我们声明了 "permissions" 中的 "scripting" 权限和 "content_scripts" 中的 "matches",使得 content script 能够与其他扩展程序或页面进行通信。

3. chrome.runtime.connect()

chrome.runtime.onMessage 用于在扩展程序中的不同脚本之间传递消息。具体来说,它允许扩展程序中的一个脚本向另一个脚本发送消息,并且可以在发送后接收响应消息。

使用该方法时,需要指定一个回调函数作为参数,当接收到消息时会调用该回调函数。回调函数会接收三个参数,分别是传递的消息、发送者信息以及发送响应消息的函数。其中,发送响应消息的函数是可选的。

它的应用场景非常广泛,例如:

  • 在 popup 页面与 content script 之间传递消息。
  • 在 background script 与 content script 之间传递消息。
  • 在不同的 content script 之间传递消息。
  • 在 options 页面与 background script 之间传递消息。

下面是一个简单的示例,演示了如何在 popup 页面和 content script 之间传递消息,并接收响应消息:

popup.html:

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8">
    <title>Popup</title>
  </head>
  <body>
    <button id="btn">发送消息</button>
    <script src="popup.js"></script>
  </body>
</html>

popup.js:

const btn = document.getElementById('btn');

// 点击按钮时向 content script 发送消息
btn.addEventListener('click', () => {
  chrome.tabs.query({ active: true, currentWindow: true }, tabs => {
    chrome.tabs.sendMessage(tabs[0].id, { greeting: 'Hello' }, response => {
      console.log(response.farewell);
    });
  });
});

content_script.js:

// 接收消息
chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
  console.log(message.greeting);
  // 发送响应消息
  sendResponse({ farewell: 'Goodbye' });
});

在上述示例中,当用户在 popup 页面点击按钮时,会向当前活动的标签页发送一条消息,消息的内容为 { greeting: 'Hello' }。标签页中的 content script 会接收到该消息,并打印出 Hello。同时,content script 会向 popup 页面发送一条响应消息,消息的内容为 { farewell: 'Goodbye' }。popup 页面会接收到该响应消息,并打印出 Goodbye。

需要注意的事项 ⚠️

  1. 消息的接收者需要在 manifest.json 中注册对应的消息处理函数,否则消息将被忽略;
  2. 消息处理函数需要返回一个 Promise 或者是一个普通的值,以便发送者能够获取到处理结果;
  3. 由于消息是异步传递的,发送者需要在发送消息后等待接收者的响应,这可以通过使用 Promise 或者回调函数来实现。

三. 应用示例

下面我们来实现一个 Google 插件,以帮助您更好地理解 Message Passing API 的作用。该插件可以帮助用户在不离开当前页面的情况下,快速搜索他们所需的内容。简单来说,就是用户可以选择一个单词或一段文字,然后通过右键点击弹出的菜单选择“Search”,该插件将在新的选项卡中打开一个搜索引擎,并使用所选的文本作为搜索关键词。

我们来看下效果:

谷歌插件开发:Message Passing API 详解(手把手带你从零探索开发谷歌插件)

那我们就开始来实现这个效果,我们先在扩展程序根目录下创建 manifest.json 文件,并添加以下配置:

{
  "manifest_version": 2,
  "name": "Quick Search",
  "version": "1.0",
  "description": "A quick search tool for selected text",
  "background": {
    "scripts": ["background.js"]
  },
  "permissions": ["contextMenus"],
  "content_scripts": [{
    "matches": ["<all_urls>"],
    "js": ["content.js"]
  }]
}

我们在 "permissions" 字段中声明了一个权限 "contextMenus",表示扩展程序需要访问浏览器上下文菜单(右键菜单)。在 "content_scripts" 字段中定义了一个脚本文件 “content.js”,该脚本会在扩展程序的内容页(所有 URL)中运行,用于实现具体的功能。

接下来我们新建background.js文件:用于处理右键点击事件并与内容脚本通信。

chrome.contextMenus.create({
  title: "Search",
  contexts: ["selection"],
  onclick: function (info, tab) {
    chrome.tabs.sendMessage(tab.id, { action: "search", selection: info.selectionText });
  }
});

chrome.runtime.onMessage.addListener(function (request, sender, sendResponse) {
  if (request.action === "openTab") {
    chrome.tabs.create({ url: request.url });
  }
});

第一步:创建了右键菜单

当用户在浏览器中选中文本后,可以右键点击,选择 “Search” 菜单项,触发搜索功能。这个功能通过使用 chrome.contextMenus.create() 函数来创建右键菜单项,传递一个对象参数,其中包括菜单项的标题、上下文(只有在选中文本时才显示该菜单项)以及点击时触发的回调函数。回调函数通过 chrome.tabs.sendMessage() 函数将所选文本发送到扩展程序的内容脚本中进行处理。

第二步:接收消息并打开新标签页

当扩展程序的内容脚本接收到 “openTab” 消息时,会触发 chrome.runtime.onMessage.addListener() 函数注册的回调函数,该函数接收一个请求对象 request,如果请求对象的 action 属性为 "openTab",则通过 chrome.tabs.create() 函数打开一个新的标签页,加载请求的 URL。这个功能用于在扩展程序的内容脚本中打开搜索结果页面,以供用户查看。

接下来我们再新建一个content.js文件:用于从内容页面与后台页面通信,以及在新的选项卡中打开搜索引擎。

chrome.runtime.onMessage.addListener(function (request, sender, sendResponse) {
  if (request.action === "search") {
    var searchUrl = "https://www.google.com/search?q=" + encodeURIComponent(request.selection);
    chrome.runtime.sendMessage({ action: "openTab", url: searchUrl });
  }
});

第一步:接收消息并处理搜索请求

当扩展程序的内容脚本接收到 “search” 消息时,会触发 chrome.runtime.onMessage.addListener() 函数注册的回调函数,该函数接收一个请求对象 request,如果请求对象的 action 属性为 “search”,则会从所选文本构造一个 Google 搜索 URL,将该 URL 发送给扩展程序的后台脚本,通过 chrome.runtime.sendMessage() 函数发送一个 “openTab” 消息,并携带搜索 URL 作为参数。

第二步:发送消息并打开新标签页

当扩展程序的后台脚本接收到 “openTab” 消息时,会触发 chrome.runtime.onMessage.addListener() 函数注册的回调函数,该函数接收一个请求对象 request,如果请求对象的 action 属性为 “openTab”,则通过 chrome.tabs.create() 函数打开一个新的标签页,加载请求的 URL。这个功能用于在扩展程序的后台脚本中打开搜索结果页面,以供用户查看。

以上就是整个插件的代码,当您选中文本并右键单击时,就会看到“Search”菜单。选择该菜单后,该插件将在新的选项卡中打开一个Google搜索引擎,并使用您选择的文本作为搜索关键词。


本节中,我们详细了解了 Message Passing API 在 Google Chrome 插件开发中的重要性和作用。我们理解了它的概念、运行方式和可配置项,并了解了如何实现跨页面通信和数据交换。

Message Passing API 为插件开发提供了强大的功能,使不同页面之间的通信变得简单而高效。通过合理地使用该API,我们可以实现更多交互和功能扩展,提升用户体验。

本节课程源码 📥

链接: pan.baidu.com/s/14URANeO8… 提取码: 8888

原文链接:https://juejin.cn/post/7233065830958399548 作者:黄勇超

(0)
上一篇 2023年5月15日 上午10:27
下一篇 2023年5月15日 上午10:38

相关推荐

发表回复

登录后才能评论