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

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

以下是控制台日志的屏幕截图 : 控制台日志

以下是涉及的代码:

popup.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> 

popup.js

这个脚本开始制作一个$.get()到一个远程网页。 variablesdata的内容可以在这里find

 $.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/>" ); }); }); }); 

在这里你可以find所有从jquery操作后的HTML。

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

的manifest.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代码,将在所有操作之后呈现在popup窗口中。 所有的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> 

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

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

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

$('div', this)select<td>所有<div>元素。 在您提供的源代码中 ,可以find以下事件处理程序:

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

通过默认的内容安全策略 ,这是被禁止的。 为了摆脱这个错误,只需在将属性插入到文档中之前删除该属性即可:

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

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

在jQuery / JavaScript可以操作DOM之前,必须先parsing它。 在你的代码中,这个工作隐式地在var TDs = $(.., data) 。 线。 这个parsing大致等于:

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

曾经听说过预加载图像? 这是一个caching图像的有用function,以便在需要时进行准备。 这可以使用(new Image).src='...'; 。 创build的<img>元素不必插入到文档中。

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

如何解决它

不要使用jQuery 。 由于您正在编写Chrome扩展程序,因此您无需担心跨浏览器的兼容性问题。 jQuery使用innerHTML技巧来parsingHTML,失败了,正如我以前所示。

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

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

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

到达解决scheme

如您所知,只要URL正确添加到清单文件中的permissions部分,就可以在Chrome扩展程序中使用跨网站请求。 我们将使用XMLHttpRequest级别2中引入的function,即responseType属性 。

 // 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的select器引擎,但大多数情况下,它也可以使用element.querySelectorAll实现。 使用var doc = xhr.response;获取文档后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() + ...); 在一个循环中。 浏览器将不得不一遍又一遍地渲染,而且,用户注意到性能下降。