代码之家  ›  专栏  ›  技术社区  ›  Claudio

控制台显示有关内容安全策略的错误和大量失败的GET请求

  •  3
  • Claudio  · 技术社区  · 12 年前

    实际上,我正在开发我的第一个Chrome扩展 即使运行平稳 我从 get() 函数来检索一些数据和一个关于代码安全性的恼人错误。

    这是一个 screenshot of the console log 以下为: Console Log

    以下是所涉及的代码:

    弹出.html

    <!doctype html>
    <html>
    <head>
        <title>NGI Little Helper - Subscribes</title>
        <link rel="stylesheet" href="popup.css">
        <!-- JavaScript and HTML must be in separate files for security. -->
        <script type="text/javascript" src="common/jquery.js"></script>
        <script type="text/javascript" src="popup.js"></script>
    </head>
    
    <body>
        <h1>Topics</h1>
        <div id="content">..:: Loading ::..</div>
    </body>
    </html>
    

    弹出.js

    此脚本开始制作 $.get() 到远程网页。变量的内容 data 可以找到 here

    $.get("http://gaming.ngi.it/subscription.php?do=viewsubscription", function(data) {
        var TDs = $('td[id*="td_threadtitle_"]', data);
        $(document).ready(function() {
            $("#content").html("<br/>");
            $.each( TDs, function() {
                //Removes useless elements from the source
                $('img[src="images/misc/tag.png"]', this).remove();
                $('span', this).remove(); //$('span[class="smallfont"]', this).remove();
                $('div[class="smallfont"]', this).remove();
                $('img[src="images/buttons/firstnew.gif"]', this).attr('src', '/img/icons/comment.gif');
                $('a[style="font-weight:bold"]', this).removeAttr("style");
                //Modify the lenght of the strings
                if ($("a[id^='thread_title_']", this).text().length > 35) {
                    $("a[id^='thread_title_']", this).text( $("a[id^='thread_title_']", this).text().substring(0, 30) + " [...]" );
                }
                //Modify the URL from relative to absolute and add the target="_newtab"
                $("a[id^='thread_']", this).attr('href', "http://gaming.ngi.it/"+ $("a[id^='thread_']", this).attr('href'));
                $("a[id^='thread_']", this).attr('target', "_newtab");
                //Send the HTML modified to the popup window
                $("#content").html($("#content").html() + $('div', this).wrap("<span></span>").parent().html() +"<br/>" );
            });
        });
    });
    

    Here 您可以从jquery中找到所有操作之后的HTML。

    老实说,我不明白为什么会出现这些错误,尤其是与安全相关的错误。我在popup.html中没有使用任何内联代码。

    宣言.json

    {
        "name": "NGI Little Helper",
        "version": "0.8.5",
        "manifest_version": 2,
        "description": "Extension per gli Utenti del forum gaming.ngi.it",
        "options_page": "fancy-settings/source/index.html",
        "background": {
            "page": "background.html"
        },
        "icons": {
            "16": "img/logo16.png",
            "48": "img/logo48.png",
            "128": "img/logo128.png"
        },
        "content_scripts": [{
            "matches": ["*://gaming.ngi.it/*"],
            "js": ["common/jquery.js", "logo_changer/logo_change.js"],
            "run_at": "document_start"
        }],
        "browser_action": {
            "default_icon": "img/icon.png",
            "default_popup": "popup.html",
            "default_title": "Visualizza Subscriptions"
        },
        "permissions": [
            "*://gaming.ngi.it/*"
        ]
    }
    

    以下是一段HTML代码,在所有操作之后将呈现到弹出窗口中。所有 div 与此类似,只是url发生了更改:

    <div>
    
                <a href="http://gaming.ngi.it/showthread.php?goto=newpost&amp;t=555954" id="thread_gotonew_555954" target="_newtab"><img class="inlineimg" src="/img/icons/comment.gif" alt="Go to first new post" border="0"></a>
    
    
    
    
                <a href="http://gaming.ngi.it/showthread.php?goto=newpost&amp;t=555954" id="thread_title_555954" target="_newtab">[All Gamez] [Frozen Synapse] S [...]</a>
    
            </div>
    

    如果需要,我可以提供完整的源代码。

    1 回复  |  直到 11 年前
        1
  •  9
  •   Rob W Sudarshan    10 年前

    让我们从最简单的问题开始:

    拒绝执行内联脚本,因为。。。

    $('div', this) 选择全部 <div> 中的元素 <td> 。在 source code 您提供的,可以找到以下事件处理程序:

    <div class="smallfont">
        <span style="cursor:pointer" onclick="window.open('member.php?u=47995', '_self')">K4raMong</span>
    </div>

    默认情况下 Content Security policy ,这是禁止的。要消除错误,只需在将属性插入文档之前删除该属性:

    element.removeAttribute('onclick'); // in jQuery: $element.removeAttr('onclick');
    

    为什么加载这些图像?我没有把它们放在文件里

    在jQuery/JavaScript能够操作DOM之前,必须首先对其进行解析。在您的代码中,这项工作是在 var TDs = $(.., data) 线此解析近似等于:

    var dummy = document.createElement('div'); // Container
    dummy.innerHTML = data;
    

    听说过预加载图像吗?这是缓存图像的一个有用功能,以便在需要时做好准备。这可以使用 (new Image).src='...'; .创建的 <img> 元素不必插入文档中。

    在您的情况下,这是不希望的行为,因为这些图像是在您的扩展中查找的。这是由于您的网页使用了 相对URL ,而不是绝对的。使用相对URL时,资源的预期位置取决于当前文档的位置。

    如何修复

    使用jQuery 。由于您正在编写Chrome扩展,因此无需担心跨浏览器兼容性。jQuery使用 innerHTML 解析HTML的技巧,失败了,正如我之前所展示的。

    JavaScript具有 DOMParser 对象,自Chrome 30以来可以按如下方式使用:

    var doc = (new DOMParser).parseFromString(data, 'text/html');
    

    您可以使用跳过从字符串到文档的手动转换 responseType 属性,如下所示。

    达成解决方案

    正如您所知,只要URL正确添加到 permissions 部分。我们将使用XMLHttpRequest级别2中引入的一个特性,即 responseType attribute

    // Fetching data
    var xhr = new XMLHttpRequest();
    xhr.open('GET', 'http://gaming.ngi.it/subscription.php?do=viewsubscription');
    xhr.onload = function() {
        var doc = xhr.response;
        // Now, you can use jQuery, since the string has been parsed.
        ...
    };
    xhr.responseType = 'document'; // Chrome 18+
    xhr.send();
    

    您可以很容易地重写代码以使用本机DOM和JavaScript而不是jQuery。大多数选择引擎使用jQuery,但大多数情况下,它也可以使用 element.querySelectorAll .使用获取文档后 var doc = xhr.response; ,请执行以下操作:

    var TDs = doc.querySelectorAll('td[id*="td_threadtitle_"]');
    var html = '';
    [].forEach.call(TDs, function(td) {
        // etc, etc. Do your job
    });
    

    你看到了吗 var html = ''; ?无论您是否使用jQuery,这都是很好的做法。从不做 element.innerHTML += ...; 甚至更糟 $element.html($element.html() + ...); 在一个循环中。浏览器将很难一次又一次地渲染它,作为用户,您会注意到性能下降。