将消息从后台脚本发送到内容脚本,然后发送到注入的脚本

将消息从后台脚本发送到内容脚本,然后发送到注入的脚本

我正在尝试将消息从后台页面发送到内容脚本,然后将该内容脚本中的消息发送到注入的脚本。我试过这个,但它没有用。

这是我的代码的样子。

的manifest.json

{
  "manifest_version": 2,

  "name": "NAME",
  "description": ":D",
  "version": "0.0",
  "permissions": [
    "tabs","<all_urls>"
  ],
  "content_scripts": [
    {
      "matches": ["<all_urls>"],
      "js": ["content_script.js"]
    }
  ],
  "web_accessible_resources": [
      "injected.js"
  ],
  "background":{
      "scripts":["background.js"]
  }}

background.js

chrome.tabs.query({active: true, currentWindow: true}, function(tabs) {
  chrome.tabs.sendMessage(tabs[0].id, {greeting: "hello"}, function(response){});});

content_script.js

var s = document.createElement('script');s.src = chrome.extension.getURL('injected.js');s.onload = function(){ 
        this.parentNode.removeChild(this);};(document.head||document.documentElement).appendChild(s);chrome.runtime.onMessage.addListener(
  function(request, sender, sendResponse) {
    document.dispatchEvent(new CustomEvent('Buffer2Remote', {todo: "LOL"}));});

injected.js

document.addEventListener('Buffer2Remote', function(e){
    alert(e.todo);});

消息发送在第一部分background - > content_script中不起作用。我的代码有什么问题吗?


慕森王
浏览 392回答 2
2回答

白猪掌柜的

由于内容脚本的注入方式,您的脚本不起作用。问题当您(重新)加载扩展程序时,与某些人的预期相反,Chrome&nbsp;不会将内容脚本注入到与清单中的模式匹配的现有选项卡中。只有在加载扩展后,任何导航都会检查URL以进行匹配,并将注入代码。那么,时间表:你打开一些标签。没有内容脚本1。您加载您的扩展程序。它的顶级代码被执行:它尝试将消息传递给当前选项卡。由于那里还没有听众,它失败了。(这可能是chrome://extensions/页面,你无论如何都不能注入)之后,如果您尝试导航/打开新选项卡,则会注入侦听器,但不再执行顶级代码。1&nbsp;- 如果您重新加载扩展程序,也会发生这种情况。如果注入了内容脚本,它将继续处理其事件/不会被卸载,但无法再与扩展进行通信。(详情见最后的附录)解决方案解决方案1:您可以先向选项卡询问您是否已准备好发送消息,并在静默时以编程方式注入脚本。考虑://&nbsp;Backgroundfunction&nbsp;ensureSendMessage(tabId,&nbsp;message,&nbsp;callback){ &nbsp;&nbsp;chrome.tabs.sendMessage(tabId,&nbsp;{ping:&nbsp;true},&nbsp;function(response){ &nbsp;&nbsp;&nbsp;&nbsp;if(response&nbsp;&&&nbsp;response.pong)&nbsp;{&nbsp;//&nbsp;Content&nbsp;script&nbsp;ready &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;chrome.tabs.sendMessage(tabId,&nbsp;message,&nbsp;callback); &nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;else&nbsp;{&nbsp;//&nbsp;No&nbsp;listener&nbsp;on&nbsp;the&nbsp;other&nbsp;end &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;chrome.tabs.executeScript(tabId,&nbsp;{file:&nbsp;"content_script.js"},&nbsp;function(){ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if(chrome.runtime.lastError)&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;console.error(chrome.runtime.lastError); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;throw&nbsp;Error("Unable&nbsp;to&nbsp;inject&nbsp;script&nbsp;into&nbsp;tab&nbsp;"&nbsp;+&nbsp;tabId); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;OK,&nbsp;now&nbsp;it's&nbsp;injected&nbsp;and&nbsp;ready &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;chrome.tabs.sendMessage(tabId,&nbsp;message,&nbsp;callback); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}); &nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;});}chrome.tabs.query({active:&nbsp;true,&nbsp;currentWindow:&nbsp;true},&nbsp;function(tabs)&nbsp;{ &nbsp;&nbsp;ensureSendMessage(tabs[0].id,&nbsp;{greeting:&nbsp;"hello"});});和//&nbsp;Content&nbsp;scriptchrome.runtime.onMessage.addListener(function(request,&nbsp;sender,&nbsp;sendResponse)&nbsp;{ &nbsp;&nbsp;if(request.ping)&nbsp;{&nbsp;sendResponse({pong:&nbsp;true});&nbsp;return;&nbsp;} &nbsp;&nbsp;/*&nbsp;Content&nbsp;script&nbsp;action&nbsp;*/});解决方案2:始终注入脚本,但要确保它只执行一次。//&nbsp;Backgroundfunction&nbsp;ensureSendMessage(tabId,&nbsp;message,&nbsp;callback){ &nbsp;&nbsp;chrome.tabs.executeScript(tabId,&nbsp;{file:&nbsp;"content_script.js"},&nbsp;function(){ &nbsp;&nbsp;&nbsp;&nbsp;if(chrome.runtime.lastError)&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;console.error(chrome.runtime.lastError); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;throw&nbsp;Error("Unable&nbsp;to&nbsp;inject&nbsp;script&nbsp;into&nbsp;tab&nbsp;"&nbsp;+&nbsp;tabId); &nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;OK,&nbsp;now&nbsp;it's&nbsp;injected&nbsp;and&nbsp;ready &nbsp;&nbsp;&nbsp;&nbsp;chrome.tabs.sendMessage(tabId,&nbsp;message,&nbsp;callback); &nbsp;&nbsp;});}和//&nbsp;Content&nbsp;scriptvar&nbsp;injected;if(!injected){ &nbsp;&nbsp;injected&nbsp;=&nbsp;true; &nbsp;&nbsp;/*&nbsp;your&nbsp;toplevel&nbsp;code&nbsp;*/}这更简单,但在扩展重新加载方面存在复杂性。重新加载扩展后,旧脚本仍然存在1,但它不再是“你的”上下文 - 因此injected将是未定义的。注意可能两次执行脚本的副作用。解决方案3:在初始化时不加选择地注入内容脚本。如果可以安全地运行相同的内容脚本两次,或者在页面完全加载后运行它,则这样做是安全的。chrome.tabs.query({},&nbsp;function(tabs)&nbsp;{ &nbsp;&nbsp;for(var&nbsp;i&nbsp;in&nbsp;tabs)&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;Filter&nbsp;by&nbsp;url&nbsp;if&nbsp;needed;&nbsp;that&nbsp;would&nbsp;require&nbsp;"tabs"&nbsp;permission &nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;Note&nbsp;that&nbsp;injection&nbsp;will&nbsp;simply&nbsp;fail&nbsp;for&nbsp;tabs&nbsp;that&nbsp;you&nbsp;don't&nbsp;have&nbsp;permissions&nbsp;for &nbsp;&nbsp;&nbsp;&nbsp;chrome.tabs.executeScript(tabs[i].id,&nbsp;{file:&nbsp;"content_script.js"},&nbsp;function()&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;Now&nbsp;you&nbsp;can&nbsp;use&nbsp;normal&nbsp;messaging &nbsp;&nbsp;&nbsp;&nbsp;}); &nbsp;&nbsp;}});我还怀疑你希望它在一些动作上运行,而不是在扩展加载上运行。例如,您可以使用浏览器操作并将代码包装在chrome.browserAction.onClicked侦听器中。关于孤立内容脚本的附录当重新加载扩展程序时,人们会希望Chrome清理所有内容脚本。但显然事实并非如此;&nbsp;内容脚本的侦听器未被禁用。但是,任何具有父扩展的消息都将失败。这应该被视为一个错误,并且可能在某些时候被修复。我要打电话给这个州“孤儿”这在以下两种情况中都不是问题:内容脚本没有页面上事件的侦听器(例如,只执行一次,或者只侦听来自后台的消息)内容脚本不对页面执行任何操作,仅发送有关事件的背景消息。但是,如果情况并非如此,那么您就会遇到一个问题:内容脚本可能正在执行某些操作,但是会失败或干扰另一个非孤立的实例。解决方法是:跟踪页面可以触发的所有事件侦听器在对这些事件采取行动之前,请向背景发送“心跳”消息。3A。如果背景响应,我们很好,应该执行操作。3B。如果消息传递失败,我们就是孤儿,应该停止;&nbsp;忽略该事件并取消注册所有侦听器。代码,内容脚本:function&nbsp;heartbeat(success,&nbsp;failure)&nbsp;{ &nbsp;&nbsp;chrome.runtime.sendMessage({heartbeat:&nbsp;true},&nbsp;function(reply){ &nbsp;&nbsp;&nbsp;&nbsp;if(chrome.runtime.lastError){ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;failure(); &nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;else&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;success(); &nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;});}function&nbsp;handler()&nbsp;{ &nbsp;&nbsp;heartbeat( &nbsp;&nbsp;&nbsp;&nbsp;function(){&nbsp;//&nbsp;hearbeat&nbsp;success &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/*&nbsp;Do&nbsp;stuff&nbsp;*/ &nbsp;&nbsp;&nbsp;&nbsp;},&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;function(){&nbsp;//&nbsp;hearbeat&nbsp;failure &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;someEvent.removeListener(handler); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;console.log("Goodbye,&nbsp;cruel&nbsp;world!"); &nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;);}someEvent.addListener(handler);背景脚本:chrome.runtime.onMessage.addListener(function(request,&nbsp;sender,&nbsp;sendResponse)&nbsp;{ &nbsp;&nbsp;if(request.heartbeat)&nbsp;{&nbsp;sendResponse(request);&nbsp;return;&nbsp;} &nbsp;&nbsp;/*&nbsp;...&nbsp;*/});
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

JavaScript