【问题标题】:Chrome extension: inserting a javascript tag and calling a functionChrome 扩展:插入 javascript 标签并调用函数
【发布时间】:2011-08-21 22:08:48
【问题描述】:

我有一个 chrome 扩展,它使用 内容脚本 来动态插入引用 an external javascript file 的脚本标记。我使用的代码是:

var html_doc = document.getElementsByTagName('head')[0]; 
var _js = document.createElement('script');  
_js.setAttribute('type', 'text/javascript'); 
_js.setAttribute('id', 'chr_js'); 
_js.setAttribute('src', 'http://unixpapa.com/js/dyna1.js'); 
if(!document.getElementById('chr_js')) 
html_doc.appendChild(_js);

外部Javascript包含以下代码:

function lfunc(){
  alert('RUNNING loaded function');
}
alert('LAST LINE of script');

当我在选项卡中加载页面时,会出现“脚本的最后一行”消息,表明脚本标签已正确插入 DOM。

我的扩展程序还有一个 按钮(即 browser_action)。现在,我希望这个按钮在被点击时调用上面定义的 lfunc()。不幸的是,我的代码根本不起作用。

我在background.html页面中使用如下代码来处理我的按钮的onClick事件:

<script>
chrome.browserAction.onClicked.addListener(function(tab) {
  chrome.tabs.executeScript(null, 
    {code: "try {lfunc()} catch (e) {alert(e);}"});
  }); // it should call lfunc()
</script>

manifest.json文件中的权限为:

"permissions": [
"tabs", "http://*/*", "https://*/*"  ]

我没有收到“RUNNING 加载函数”消息,而是收到错误消息“ReferenceError: lfunc is not defined”。

我做错了什么?

【问题讨论】:

  • 外部脚本和内容脚本是完全不同的(私有!)范围。他们不能使用彼此的代码。然而,他们确实为此发明了一些东西(有点):sendRequest 和 onRequest 但是为什么你要加载外部脚本?
  • 如果您将 lfunc 安装到窗口的全局范围并像那样执行它,可能会起作用...我会尝试一下 =)
  • 好吧,我无法让它工作。内容脚本和背景页面可以对话,但似乎它们都无法访问文档窗口中的用户内容。 (他们确实可以访问 DOM 和标准 JS,但不能访问用户添加的功能,例如您的外部脚本)。
  • 非常感谢鲁迪的帮助。我想加载一个外部脚本,以便在那里打包我的扩展程序的大部分功能,以便我可以在其他浏览器的扩展程序中重用它(尤其是 IE)。通过这样做,我还可以通过修改外部 JS 文件轻松地从扩展更新代码。至少这是理论:)
  • 那么,有没有办法从我的后台页面执行外部JS文件?

标签: javascript function google-chrome background


【解决方案1】:

我需要调用其中一个页面脚本中的函数...

location = 'javascript:callToTheFunction(param,param,..)' did it.  

我说的是内容

【讨论】:

    【解决方案2】:

    将alert('It doesn't work'); 替换为alert(e);

    这应该让您更好地了解错误是什么。请发布错误。

    【讨论】:

    • 我插入了 alert(e) 并重新编辑了我的问题,提供了一些您可能会觉得有用的更多信息。我得到的错误是“ReferenceError: lfunc is not defined”。如果我将外部 Javascript 的内容转储到文件 myContentScript.js 中并将其作为内容脚本添加到 manifest.json 中,那么整个事情就可以了!但这对我来说不够足够好,因为我希望能够使用托管在扩展包中没有的服务器中的外部 javascript...所以问题仍然存在,为什么不行吗?
    【解决方案3】:

    您可以执行外部 JS 文件(通过将其注入 DOM(扩展名中的document))。外部 JS 文件也可以访问本地 DOM。

    这两者之间不可能交流:

    • 扩展程序无法访问用户添加的 Javascript(非本地):
      扩展的 JS 无法访问页面的 jQuery 对象,但可以访问其 document.body。
    • 用户添加的 Javascript(页面的 JS 或您添加的外部 JS)无权访问扩展:
      从页面中,您无法访问 chrome API,例如书签、标签、浏览器操作等。

    出于安全原因,这是故意这样做的。

    我所说的(sendRequest 和 onRequest)是“内容脚本”和扩展脚本/背景页面之间的通信。在你的情况下无关=)对不起。

    答案

    >由于两者之间缺乏通信能力,我无法从扩展中调用外部JS文件中的特定函数

    没错。

    > 我所能做的就是让我的扩展将外部 JS 文件注入到 DOM 中。这将执行外部 JS 文件中要执行的任何内容

    没错。 ext JS 可以包含即时操作和计时器等,就像正常加载的 JS(在网页本身中)一样。

    > 扩展的代码启动粒度是在外部 JS 级别,而不是在 JS 函数级别

    JS function level 是什么意思?扩展JS?

    PS
    chrome.tabs.executeScript 并不像你想象的那么酷。基本上它所做的是在页面的上下文中执行一个脚本(如content_scripts)。但是,它有与content_scripts 相同的限制:它可以访问 DOM 和本机 JS 功能,而不是用户添加的 JS。一个例子:

    // Inside a `background_page`:
    chrome.tabs.executeScript(null, {
        "code": "document.body.removeChild(document.body.firstChild);"
    });
    

    这是可行的,因为只需要访问页面的(始终存在的)DOM。以下将不起作用(假设 jQuery 包含在网页本身中):

    // Still inside a `background_page`:
    chrome.tabs.executeScript(null, {
        "code": "jQuery('input').remove();"
    });
    

    这不起作用,因为jQuery 是一个外来的、非本地的、用户添加的 JS 对象,扩展程序无法访问(background_page 和 content_scripts)。
    我真的不明白最后一个限制的原因,但这都是关于 Chrome 中的沙盒和安全性 =) 我猜这是一件好事......

    顺便说一句
    我认为你的问题的解决方案很简单......你可以让browser_action将外部JS注入页面的DOM。够了,对吧?外部 JS 包含逻辑和实际的函数调用。更好的解决方案,因为只有在按下/触发browser_action(按钮)时才会加载外部JS。一个非常轻微的缺点:非常短的延迟(= 在推送 browser_action 后下载外部 JS)。

    我是否可以再次建议:将所有扩展 JS 放入扩展中。这将允许离线功能,并且永远不需要(其他)连接到第三方服务器。

    【讨论】:

    • 谢谢鲁迪!如果我理解正确的话,由于两者之间缺乏通信能力,我无法从扩展中调用外部 JS 文件中的特定函数。我所能做的就是让我的扩展将外部 JS 文件注入到 DOM 中。这将执行外部 JS 文件中要执行的任何内容。扩展的代码启动粒度是外部 JS 级别,而不是 JS 函数级别。是这样吗?
    • 在我的回答中回答你的评论以及关于chrome.tabs.executeScript的一点点
    • 感谢您的示例和您的建议。现在我正在处理的问题对我来说非常清楚。我认为问题已得到解答。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-05-25
    • 1970-01-01
    • 2019-04-20
    • 1970-01-01
    • 2018-11-14
    • 2013-11-18
    • 1970-01-01
    相关资源
    最近更新 更多