我有一个非常奇怪的问题,我开发了一个使用内容脚本和后台脚本(使用chrome.runtime.connect
)和nativemessaging之间的消息传递的webextension。
我面临的问题是,当我安装扩展程序(事先从商店手动然后连接到我的网站,一切正常工作,chrome.runtime.connect工作并返回一个有效的端口到背景脚本。
但是,当我从我的网站进行内联安装扩展以解决事实,必须导航到网页中有内容脚本时,我手动将内容脚本注入我的页面
function injectContentScript() {
var s = document.createElement("script");
s.setAttribute("src", "chrome-extension://<extensionid>/content.js");
document.head.appendChild(s);
}
和完全相同的内容脚本但手动注入的行为并不相同。 chrome.runtime.connect返回一个null对象,chrome.runtime.lastError给我
无法建立连接。接收端不存在。
我正在呼叫发送方(content.js - 手动注入的内容脚本)chrome.runtime.connect(extensionID)
其中,扩展ID是chrome webstore生成的扩展的ID。并在接收方(background.js - 扩展背景脚本)chrome.runtime.onConnect.addListener(onPortConnected);
我不确定如何调试此问题,也许这是一个时间问题? 即使使用内联安装(我已添加日志并通过chrome扩展管理器中的background.html对其进行调试),后台脚本也能很好地执行
非常感谢任何帮助!
答案 0 :(得分:3)
您有两种情况。
您的内容脚本content.js
在导航时正常执行,作为清单中定义的内容脚本。
在这种情况下,它在附加到页面的特殊JS上下文中执行,并为内容脚本保留。有关说明,请参阅Execution Environment文档部分。它与网页隔离,被视为扩展的一部分(尽管权限较低)。
从内容脚本连接时,chrome.runtime.connect()
被视为扩展部分之间的内部通信。因此,虽然您可以提供扩展ID,但不需要它。
更重要的是,在这种情况下提出的事件是chrome.runtime.onConnect
。
你想要的&#34;立即注入内容脚本&#34;从网页调用的代码完全不同。
而不是创建新的执行上下文,而是将代码直接添加到页面中;它不被视为扩展程序的一部分,无权访问扩展API。
通常,对chrome.runtime.connect()
的调用会失败,因为这不是暴露给网页的功能;但是,您还声明了externally_connectable
,因此它会将专门公开到您的网页。
在这种情况下,为connect
传递扩展名ID为必需。你已经这样做了,所以电话就成功了。
然而,这是导致其失败的原因:相应的事件不再是onConnect
,而是onConnectExternal
!
应该做的是:
不混合在非常不同的上下文中运行的代码。
如果您需要从网页到背景的通信,请始终从网页进行,有时不从内容 - 有时从页面进行。
这样你只需要听onConnectExternal
,它就不再需要内容脚本(如果它是唯一的功能)。
您不必从chrome-extension://<extensionid>/
获取代码;您可以直接将其添加到您网站的代码中,并可能避免使用web_accessible_resources
。
如果您确实想要在首次运行时注入内容脚本,请参阅示例this answer。
相关阅读:How to properly handle chrome extension updates from content scripts