将 HTML 附加到 XUL(Firefox 扩展)
我有这个 javascript,它从服务器获取 html 部分。我能够在警报消息中返回 html,它是正确的代码。
ajax: function(url){
var request = Components.classes["@mozilla.org/xmlextras/xmlhttprequest;1"]
.createInstance(Components.interfaces.nsIXMLHttpRequest);
request.onreadystatechange = function() {
if (request.readyState == 4) {
// only if "OK"
if (request.status == 200) {
var popup = document.getElementById("ajax"); // a <menupopup> element
var txt = request.responseText;
alert(txt);
popup.appendChild(txt);
} else {
alert("There was a problem retrieving the XML data:\n" +
request.statusText);
}
}
};
request.open("GET", url, true);
request.send(null);
}
从服务器返回的 xul/html:
<menuitem>
<html:h2><html:a href="http://google.com">Google</html:a></html:h2>
<html:p><html:table><html:tr><html:td>xxxx</html:td></html:tr></html:table></html:p>
</menuitem>
<menuitem>
<html:h2><html:a href="http://yahoo.com">Yahoo</html:a></html:h2>
<html:p><html:table><html:tr><html:td>yyyy</html:td></html:tr></html:table></html:p>
</menuitem>
我的 xul 页面:
...更多代码
<menu class="menu" label="test">
<menupopup id="ajax" width="450" height="700" onpopupshowing="myextension.ajax('http://www.myserver.com/phpscript.php'>
</menupopup>
</menu>
现在,如果我将 html 直接附加到带有 id ajax 的 menupopup 上,它就会按预期工作。当我使用appendChild附加它时,它没有。我知道我不能使用appendChild,但XUL 中似乎没有与innerHTML 等效的东西。我无法控制从服务器返回的 xul/html,因此我无法使用 DOM 方法来添加内容并绕过 html。
我尝试使用 HTMLParser https://developer.mozilla.org/en/Code_snippets/HTML_to_DOM将其转换为 DOM 对象,但这似乎不起作用,我相信因为它剪切了 标签。
任何想法如何将 HTML 附加到菜单弹出窗口,以便我可以将它们显示为菜单项。
好吧,我尝试了 iframe 方法:
ajax: function(url){
var request = Components.classes["@mozilla.org/xmlextras/xmlhttprequest;1"]
.createInstance(Components.interfaces.nsIXMLHttpRequest);
request.onreadystatechange = function() {
if (request.readyState == 4) {
// only if "OK"
if (request.status == 200) {
var frame = document.getElementById("frame");
frame.setAttribute("src", "data:text/html," + encodeURIComponent(request.responseText));
} else {
alert("There was a problem retrieving the XML data:\n" + request.statusText);
}
}
};
request.open("GET", url, true);
request.send(null);
}
这
<iframe id="frame" type="content" src="" />
似乎不起作用。但是,如果我对encodeURIComponent(request.responseText)发出警报,它就会被正确编码。更重要的是,如果我像这样直接将它添加到 iframe 中:
<iframe type="content" src="data:text/html,%3Chtml%3E%0A%3Cbody%3E%0A%3Cp%3EHello%20everyone%3C%2Fp%3E%0A%09%3C%2Fbody%3E%0A%3C%2Fhtml%3E%0A%0A"/>
它不起作用,因为要显示 html,它需要在标签内,但 html 包含许多不同的项目,每个项目都应该在自己的标签中。简单地添加到 html 中是行不通的。
I have this javascript which fetches a html part from the server. I'm able to return the html in an alert message and it's the correct code.
ajax: function(url){
var request = Components.classes["@mozilla.org/xmlextras/xmlhttprequest;1"]
.createInstance(Components.interfaces.nsIXMLHttpRequest);
request.onreadystatechange = function() {
if (request.readyState == 4) {
// only if "OK"
if (request.status == 200) {
var popup = document.getElementById("ajax"); // a <menupopup> element
var txt = request.responseText;
alert(txt);
popup.appendChild(txt);
} else {
alert("There was a problem retrieving the XML data:\n" +
request.statusText);
}
}
};
request.open("GET", url, true);
request.send(null);
}
the xul/html returned from the server:
<menuitem>
<html:h2><html:a href="http://google.com">Google</html:a></html:h2>
<html:p><html:table><html:tr><html:td>xxxx</html:td></html:tr></html:table></html:p>
</menuitem>
<menuitem>
<html:h2><html:a href="http://yahoo.com">Yahoo</html:a></html:h2>
<html:p><html:table><html:tr><html:td>yyyy</html:td></html:tr></html:table></html:p>
</menuitem>
My xul page:
... some more code
<menu class="menu" label="test">
<menupopup id="ajax" width="450" height="700" onpopupshowing="myextension.ajax('http://www.myserver.com/phpscript.php'>
</menupopup>
</menu>
Now if I attach the html directly to the menupopup with id ajax it works as expected. When I attach it using appendChild it doesn't. I know I can't use appendChild but there seems to be no equivalent to innerHTML in XUL. I have no control over the xul/html returned from the server so I can't use the DOM methods to add the content and bypass the html.
I tried using HTMLParser https://developer.mozilla.org/en/Code_snippets/HTML_to_DOM to convert it into a DOM object but that doesn't seem to work, I believe because it cuts of the <menuitem>
tag.
Any ideas how to attach the HTML to a menupopup so I can display them as menuitems.
Ok I tried the iframe approach:
ajax: function(url){
var request = Components.classes["@mozilla.org/xmlextras/xmlhttprequest;1"]
.createInstance(Components.interfaces.nsIXMLHttpRequest);
request.onreadystatechange = function() {
if (request.readyState == 4) {
// only if "OK"
if (request.status == 200) {
var frame = document.getElementById("frame");
frame.setAttribute("src", "data:text/html," + encodeURIComponent(request.responseText));
} else {
alert("There was a problem retrieving the XML data:\n" + request.statusText);
}
}
};
request.open("GET", url, true);
request.send(null);
}
with
<iframe id="frame" type="content" src="" />
This doesn't seem to work. However if I do an alert of the encodeURIComponent(request.responseText) it's correctly encoded. Evenmore if I directly add it to the iframe like this:
<iframe type="content" src="data:text/html,%3Chtml%3E%0A%3Cbody%3E%0A%3Cp%3EHello%20everyone%3C%2Fp%3E%0A%09%3C%2Fbody%3E%0A%3C%2Fhtml%3E%0A%0A"/>
it does not work because to display the html it needs to be within tags but the html contains many different items which should be each in their own tag. Simply adding to the html is not working.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
首先是正确的答案,这并不是您真正想要的,但重要的是要省略:
不要将远程检索的 HTML 或 javascript 代码附加/注入/任何内容到 XUL 或 chrome 代码范围中!
像这样的事情总是一个安全漏洞。 JS 是可执行的,HTML 也可能包含可执行位(例如 javascript: 协议)。任何注入的代码都将以完整的浏览器权限运行,这会转换为操作系统用户权限(在 Windows XP 上会转换为管理员权限)。
您需要转义 html,或者解析它并只保留安全位。
您不能信任远程代码,即使它源自您自己的服务器:
顺便说一句:由于上述原因,将远程检索的代码或 HTML 附加/注入/任何内容到 chrome 空间将导致 addons.mozilla.org 上受影响的附加组件版本被拒绝。
现在是技术上正确的答案,但不要与远程检索和清理的 HTML 一起使用:
xmlns:html="http://www.w3.org/1999/ xhtml"
)appendElement()
文本,而只能是真正的 DOM 元素。因此,您必须先将任何文本解析为 DOM。使用有效的 XML 最简单(DOMParser);可以通过隐藏的 iframe 来标记汤的内容。adoptNode
来自不同 DOM 的任何元素,First the correct answer, which isn't really what you're looking for, but to important to omit:
Do not append/inject/whatever remotely retrieved HTML or javascript code into XUL or chrome code scopes!
Stuff like this always is a security vulnerability. JS is executable, and HTML may contain executable bits as well (e.g. javascript: protocol). Any injected code will run with full browser privileges, which translates to OS user privileges (which on Windows XP translates to Administrator privileges).
You need to either escape the html, or parse it and only leave secure bits in.
You cannot trust remote code, even if it originates from your own servers:
BTW: Appending/injecting/whatever remotely retrieved code or HTML into chrome space will lead to rejection of the affected versions of your add-on on addons.mozilla.org for the reason stated above.
Now the technically correct answer, but do not use with remotely retrieved and sanitized HTML:
xmlns:html="http://www.w3.org/1999/xhtml"
)appendElement()
text, but only real DOM elements. Hence you must parse any text into a DOM before. Easiest with valid XML (DOMParser); possible for tag soup stuff via a hidden iframe.adoptNode
any Elements from different DOMs您的代码确实存在安全漏洞,您绝对不应该这样做。然而,有一种相对简单的方法可以安全地做到这一点(重要的是:这是假设您的 XUL 没有在浏览器的内容区域中运行)。您将一个 iframe 放入 menupopup:
然后您可以使用 data: URL 将数据加载到该框架中。这里重要的部分是 type="content" ,这在您的代码(chrome)和您加载的代码(内容)之间创建了安全边界。这就是为什么您的 XUL 文档不在浏览器的内容区域中很重要 - 那么您已经位于安全边界的“内容”一侧,您无法建立另一个边界。
实际上将数据放入框架的工作方式如下:
有关更多信息,请参阅 https://developer.mozilla.org/ En/Displaying_web_content_in_an_extension_without_security_issues(本文是专门为 RSS 读者编写的)。
Your code is indeed a security vulnerability, you should never do it like that. There is a relatively easy way to do it securely however (important: this is assuming that your XUL isn't running in the browser's content area). You put an iframe into your menupopup:
You can then load your data into that frame using a data: URL. The important part here is type="content" here, this creates a security boundary between your code (chrome) and the code you loaded (content). Which is why it is important that your XUL document isn't in the browser's content area - then you are already on the "content" side of the security boundary, you cannot establish another one.
Actually putting the data into the frame works like this:
For more information see https://developer.mozilla.org/En/Displaying_web_content_in_an_extension_without_security_issues (this article was written specifically with RSS readers in mind).