我有一个网页,其中包含自己的脚本和变量,我需要执行这些脚本和变量并从扩展程序的Background.js中检索返回值。
我了解(我认为!),为了与网页进行交互,必须通过chrome.tabs.executeScript或ContentScript完成此操作,但是因为代码必须在原始页面的上下文中执行(为了具有作用域) (脚本和变量),则需要先将其注入页面。
到目前为止,这就是我所得到的…
网页代码 (我想与之交互):
<html> <head> <script> var favColor = "Blue"; function getURL() { return window.location.href; } </script> </head> <body> <p>Example web page with script content I want interact with...</p> </body> </html>
manifest.json :
{ // Extension ID: behakphdmjpjhhbilolgcfgpnpcoamaa "name": "MyExtension", "version": "1.0", "manifest_version": 2, "description": "My Desc Here", "background": { "scripts": ["background.js"] }, "icons": { "128": "icon-128px.png" }, "permissions": [ "background", "tabs", "http://*/", "https://*/", "file://*/", //### (DEBUG ONLY) "nativeMessaging" ] }
background.js
codeToExec = ['var actualCode = "alert(favColor)";', 'var script = document.createElement("script");', ' script.textContent = actualCode;', '(document.head||document.documentElement).appendChild(script);', 'script.parentNode.removeChild(script);'].join('\n'); chrome.tabs.executeScript( tab.id, {code:codeToExec}, function(result) { console.log('Result = ' + result); } );
我意识到代码当前只是在“更改” favColor变量(这只是一项测试,以确保我可以看到它正常工作)。但是,如果我尝试返回该变量(通过将其保留为最后一条语句或说“ returnfavColor”),则executeScript回调将永远没有该值。
因此,这里似乎有(至少)三个级别:
…我想知道从1级到3级(以上)并返回值的推荐方法是什么?
在此先感谢:o)
您完全理解3层上下文分离。
为了进行通信,这些层使用不同的方法:
*通过Chrome API进行 *背景 <->内容交流。 最原始的是的回调executeScript,但除了单行代码外,这对于任何其他情况都是不切实际的。 常用的方法是使用Messaging。 不常见,但可以使用chrome.storage及其onChanged事件进行通信。
executeScript
chrome.storage
onChanged
页面 <->扩展名不能使用相同的技术。 由于注入的页面上下文脚本在技术上与页面本身的脚本没有什么区别,因此您正在寻找一种与扩展程序对话的网页方法。有两种可用的方法:
chrome.*
"externally_connectable"
好处是直接与扩展程序对话,但缺点是 需要从中专门将您正在使用的域白名单加入白名单 ,并且您需要跟踪扩展名ID(但是由于要注入代码,因此您可以提供带有ID的代码)。如果需要在任何域上使用它,则不合适。
该文档演示了如何使用window.postMessage此效果。从概念上讲,使用自定义事件更为清晰。
window.postMessage
这种方法的缺点是 要求内容脚本充当代理 。这些脚本中必须包含以下内容:
window.addEventListener("PassToBackground", function(evt) { chrome.runtime.sendMessage(evt.detail); }, false);
而后台脚本使用chrome.runtime.onMessage侦听器对此进行处理。
chrome.runtime.onMessage
我建议您编写一个单独的内容脚本,并executeScript使用file属性而不是进行调用code,而不要依赖其回调。消息传递更加简洁,可以多次将数据返回到后台脚本。
file
code