onclick 或内联脚本在扩展中不起作用

IT技术 javascript google-chrome-extension onclick firefox-addon-webextensions
2021-01-31 19:36:51

这似乎是最容易做的事情,但它就是行不通。在普通浏览器中,.html 和 .js 文件可以完美运行,但在 Chrome/Firefox 扩展中,该onClick函数没有执行它应该做的事情。

.js 文件:

function hellYeah(text) {
  document.getElementById("text-holder").innerHTML = text;
}

.html 文件:

<!doctype html>
<html>
  <head>
    <title>
      Getting Started Extension's Popup
    </title>
    <script src="popup.js"></script>
  </head>
  <body>
    <div id="text-holder">
      ha
    </div>
    <br />
    <a onClick=hellYeah("xxx")>
      hyhy
    </a>
  </body>
</html>

所以基本上一旦用户点击“hyhy”,“ha”应该变成“xxx”。再次 - 它在浏览器中完美运行,但在扩展中不起作用。你知道为什么吗?以防万一我也在下面附上 manifest.json。

清单.json:

{
  "name": "My First Extension",
  "version": "1.0",
  "manifest_version": 2,
  "description": "The first extension that I made.",
  "browser_action": {
    "default_icon": "icon.png",
    "default_popup": "popup.html"
  },
  "permissions": [
    "http://api.flickr.com/"
  ]
}
5个回答

Chrome 扩展程序不允许您使用内联 JavaScript(文档)。
Firefox WebExtensions(文档)也是如此。

你将不得不做类似的事情:

为链接分配一个 ID(<a onClick=hellYeah("xxx")>变成<a id="link">),并用于addEventListener绑定事件。将以下内容放入您的popup.js文件中:

document.addEventListener('DOMContentLoaded', function() {
    var link = document.getElementById('link');
    // onClick's logic below:
    link.addEventListener('click', function() {
        hellYeah('xxx');
    });
});

popup.js 应该作为单独的脚本文件加载:

<script src="popup.js"></script>
@teeZee 为了将来参考,在代码周围加上反引号 (`) 以在注释中对其进行格式化。 Like this.
2021-03-13 19:36:51
我的弹出窗口中的标记是在运行时生成的(例如,带有不可预测值的 <a> 标签)。我已经将 <a> 标签的 id 设置为等于 <a> 标签 innerhtml 的值: <a href="#" id="xxxxxx">xxxxxx</a> <a href="# " id="abc123">abc123</a> 但我需要将值传递给 javascript 以在单击它们时进行处理......我该怎么做?最终,只是让 javascript 提醒点击的 href 的值将是一个好的开始。
2021-03-22 19:36:51
我得到了这样的信息:“拒绝执行内联脚本,因为它违反了以下内容安全策略指令:“script-src 'self' chrome-extension-resource:”。
2021-03-23 19:36:51
请注意,即使您不能进行内联onclick="handleClick()",您仍然可以使用el.onclick = handleClick.
2021-03-26 19:36:51
Javascript 不能在您的 HTML 文件中用于扩展。您必须从外部源加载所有 javascript。就像是<script src="javascript.js"></script>
2021-04-02 19:36:51

原因

这不起作用,因为 Chrome禁止通过内容安全策略在扩展程序中使用任何类型的内联代码

不会执行内联 JavaScript。此限制禁止内联<script>内联事件处理程序(例如<button onclick="...">)。

如何检测

如果这确实是问题所在,Chrome 会在控制台中产生以下错误:

拒绝执行内联脚本,因为它违反了以下内容安全策略指令:“script-src 'self' chrome-extension-resource:”。启用内联执行需要“unsafe-inline”关键字、哈希(“sha256-...”)或随机数(“nonce-...”)。

要访问弹出窗口的 JavaScript 控制台(通常对调试很有用),请右键单击扩展程序的按钮并从上下文菜单中选择“检查弹出窗口”。

此处提供有关调试弹出窗口的更多信息

怎么修

需要删除所有内联 JavaScript。Chrome 文档中一个指南

假设原来的样子:

<a onclick="handler()">Click this</a> <!-- Bad -->

需要删除该onclick属性并给元素一个唯一的 id:

<a id="click-this">Click this</a> <!-- Fixed -->

然后从脚本附加侦听器(.js假设必须在文件中popup.js):

// Pure JS:
document.addEventListener('DOMContentLoaded', function() {
  document.getElementById("click-this").addEventListener("click", handler);
});

// The handler also must go in a .js file
function handler() {
  /* ... */
}

注意DOMContentLoaded事件中的包装这确保元素在执行时存在。现在添加脚本标签,例如在<head>文档中:

<script src="popup.js"></script>

如果您使用的是 jQuery,则另一种选择:

// jQuery
$(document).ready(function() {
  $("#click-this").click(handler);
});

放宽政策

问:错误提到了允许内联代码的方法。我不想/不能更改我的代码,如何启用内联脚本?

A:不管错误是什么,你都不能启用内联脚本

没有机制可以放宽对执行内联 JavaScript 的限制。特别是,设置包含的脚本策略'unsafe-inline'将不起作用。

更新:从 Chrome 46 开始,可以将特定的内联代码块列入白名单:

从 Chrome 46 开始,可以通过在策略中指定源代码的 base64 编码哈希来将内联脚本列入白名单。该散列必须以使用的散列算法(sha256、sha384 或 sha512)作为前缀。有关示例,请参阅元素的哈希用法<script>

但是,我不太容易看到使用它的理由,并且它不会启用内联属性,例如onclick="code".

关于如何将此解决方案匿名化以便它可以用于具有生成的 div 名称的 angular 应用程序的任何想法?我无法创建事件侦听器,因为我的 ng repeat 中的每个项目的按钮名称都必须是唯一的... :(
2021-03-21 19:36:51
如果我想用类名而不是Id来做同样的事情..我试过了,但没有运气'
2021-03-31 19:36:51

我遇到了同样的问题,不想重写代码,所以我写了一个函数来修改代码并创建内联声明事件:

function compile(qSel){
    var matches = [];
    var match = null;
    var c = 0;

    var html = $(qSel).html();
    var pattern = /(<(.*?)on([a-zA-Z]+)\s*=\s*('|")(.*)('|")(.*?))(>)/mg;

    while (match = pattern.exec(html)) {
        var arr = [];
        for (i in match) {
            if (!isNaN(i)) {
                arr.push(match[i]);
            }
        }
        matches.push(arr);
    }
    var items_with_events = [];
    var compiledHtml = html;

    for ( var i in matches ){
        var item_with_event = {
            custom_id : "my_app_identifier_"+i,
            code : matches[i][5],
            on : matches[i][3],
        };
        items_with_events.push(item_with_event);
        compiledHtml = compiledHtml.replace(/(<(.*?)on([a-zA-Z]+)\s*=\s*('|")(.*)('|")(.*?))(>)/m, "<$2 custom_id='"+item_with_event.custom_id+"' $7 $8");
    }

    $(qSel).html(compiledHtml);

    for ( var i in items_with_events ){
        $("[custom_id='"+items_with_events[i].custom_id+"']").bind(items_with_events[i].on, function(){
            eval(items_with_events[i].code);
        });
    }
}

$(document).ready(function(){
    compile('#content');
})

这应该从所选节点中删除所有内联事件,并使用 jquery 重新创建它们。

此代码未正确执行,请以正确的方式指导我
2021-03-28 19:36:51

我决定发布我在我的案例中使用的示例。我尝试使用脚本替换 div 中的内容。我的问题是 Chrome 无法识别/未运行该脚本。

更详细地我想做的是:点击一个链接,然后点击一个链接来“读取”一个外部 html 文件,它将被加载到一个 div 部分。

  • 我发现通过将脚本放在 ID 被调用的 DIV 之前,脚本不起作用。
  • 如果脚本在另一个 DIV 中,它也不起作用
  • 脚本必须使用 document.addEventListener('DOMContentLoaded', function() 进行编码,因为它被告知

        <body>
        <a id=id_page href ="#loving"   onclick="load_services()"> loving   </a>
    
            <script>
                    // This script MUST BE under the "ID" that is calling
                    // Do not transfer it to a differ DIV than the caller "ID"
                    document.getElementById("id_page").addEventListener("click", function(){
                    document.getElementById("mainbody").innerHTML = '<object data="Services.html" class="loving_css_edit"; ></object>'; });
                </script>
        </body>
    
      <div id="mainbody" class="main_body">
            "here is loaded the external html file when the loving link will 
             be  clicked. "
      </div>
    
我不确定......如果它是 100% 正常工作。删除了 txt/html 定义。
2021-03-09 19:36:51

如前所述,出于安全原因,Chrome 扩展程序不允许使用内联 JavaScript,因此您也可以尝试此解决方法。

HTML文件

<!doctype html>
    <html>
        <head>
            <title>
                Getting Started Extension's Popup
            </title>
            <script src="popup.js"></script>
        </head>
        <body>
            <div id="text-holder">ha</div><br />
            <a class="clickableBtn">
                  hyhy
            </a>
        </body>
    </html>
<!doctype html>

弹出窗口.js

window.onclick = function(event) {
    var target = event.target ;
    if(target.matches('.clickableBtn')) {
        var clickedEle = document.activeElement.id ;
        var ele = document.getElementById(clickedEle);
        alert(ele.text);
    }
}

或者,如果您包含一个 Jquery 文件,那么

window.onclick = function(event) {
    var target = event.target ;
    if(target.matches('.clickableBtn')) {
        alert($(target).text());
    }
}