[英]Firefox Addon SDK: Loading addon file into iframe
我想将一个resource://
链接分别加载到我的Firefox插件中的本地文件到网页中的iframe
。
原因是,出于安全原因,资源应该可视地嵌入到网页中,而不是让网站访问它的DOM。
这个问题在过去的各个地方已经讨论过了,例如这里(没有解决方案): https : //bugzilla.mozilla.org/show_bug.cgi?id = 792479
由于大多数帖子都比较陈旧,我想问一下,如果在此期间有任何新的解决方案或解决方法。
我认为我在错误或在jetpack的ML中提出了一个糟糕的解决方法,基本上是在data:
url中转换你的resource://
(使用data.load
加载HTML内容,然后编码并附加为前缀,所以这样的事情应该有效:
/* main.js */
const { data } = require('sdk/self');
// just an example, you can use `tab.attach` too
require('sdk/page-mod').PageMod({
include: '*',
contentScriptFile: data.url('content.js'),
contentScriptOptions: {
content: encodeURIComponent(data.load('index.html'))
}
});
/* content.js */
let iframe = document.body.appendChild(document.createElement('iframe'));
iframe.setAttribute('sandbox', 'allow-scripts');
// maybe you want also use the seamless attribute, see:
// https://developer.mozilla.org/en-US/docs/Web/HTML/Element/iframe
iframe.contentWindow.location.href = 'data:text/html;charset=utf-8,' + self.options.content;
这当然是一种解决方法,我希望你提到的错误很快就会解决。 请注意,通过这种方式,您无法直接从iframe与父文档进行通信,但这也意味着您无法绕过,这就是您想要阻止的。
当然,您仍然可以使用附加代码在iframe和父文档之间进行通信(您需要附加内容脚本并使用port
和postMessage
)。
编辑:更改了url的设置方式,否则仍然可以从父文档中获取src
属性,并包含完整的HTML。
我使用了这里提出的解决方案 。
它是通过创建由Firefox插件处理的特殊协议来实现的,该插件又从其文件夹中请求资源。
请注意,如果资源文件夹可能包含非公开的内容,那么我会添加其他检查以仅允许那些真正可以通过Web访问的资源。
附上上述帖子的自定义协议代码可在此处获得 :
/*
Makes any file within the data directory available to use in an iframe.
Replace this: require("sdk/self").data.url(...)
With this: require("name-of-this-file").url(...)
*/
var { Class } = require('sdk/core/heritage');
var { Unknown, Factory } = require('sdk/platform/xpcom');
var { Cc, Ci, Cr } = require('chrome');
var self = require("sdk/self");
var resourceProtocolHandler = Cc["@mozilla.org/network/io-service;1"]
.getService(Ci.nsIIOService)
.getProtocolHandler('resource');
var scheme = "res-" + self.id.toLowerCase().replace(/[^a-z0-9+\-\.]/g, "-");
var AddonProtocolHandler = Class({
extends: Unknown,
interfaces: ['nsIProtocolHandler'],
scheme: scheme,
defaultPort: -1,
protocolFlags: Ci.nsIProtocolHandler.URI_STD
| Ci.nsIProtocolHandler.URI_LOADABLE_BY_ANYONE
| Ci.nsIProtocolHandler.URI_SAFE_TO_LOAD_IN_SECURE_CONTEXT,
newURI: function(spec, originCharset, baseURI) {
let uri = Cc["@mozilla.org/network/standard-url;1"].createInstance(Ci.nsIStandardURL);
uri.init(uri.URLTYPE_STANDARD, this.defaultPort, spec, originCharset, baseURI);
return uri.QueryInterface(Ci.nsIURI);
},
newChannel: function(uri) {
if (uri.spec.indexOf(exports.url("")) != 0) {
throw Cr.NS_ERROR_ILLEGAL_VALUE;
}
var resourceUri = resourceProtocolHandler.newURI(uri.spec.replace(scheme + "://", "resource://"), uri.originCharset, null);
var channel = resourceProtocolHandler.newChannel(resourceUri);
channel.originalURI = uri;
return channel;
},
allowPort: (port, scheme) => false
});
Factory({
contract: "@mozilla.org/network/protocol;1?name=" + scheme,
Component: AddonProtocolHandler
});
exports.url = function(url) {
return self.data.url(url).replace("resource://", scheme + "://");
};
附加说明 :对于page
脚本(不是content
脚本),此自定义协议有助于加载iframe
和其他HTML元素,但不能加载XMLHttpRequest
或Worker
。 对于后者,仍然存在跨源限制并且引发安全性错误:在XMLHttpRequest
情况下“访问受限制的URI被拒绝”,并且“操作是不安全的”。 为Worker
。
相反,在Chrome下,允许使用XMLHttpRequest
到web_accessible_resources
。 Worker
也没有在Chrome下实现对web_accessible_resources
访问。
但是对于Workers
您可以将此自定义协议URL用于importScripts
方法。 使用它您还可以解决将自定义资源加载到Workers
。 此代码也适用于Chrome,作为使用XMLHttpRequest
的替代方法。
var code = "self.onmessage = function (message)\
{\
self.onmessage = null;\
self.importScripts(message.data);\
};";
var blob = new Blob([code], {type: 'application/javascript'});
var blobUrl = URL.createObjectURL(blob);
var w = new Worker(blobUrl);
w.postMessage(*webAccessibleResourceUrl*);
URL.revokeObjectURL(blobUrl);
我正在使用zer0的想法。 但是,在具有content-security-policy的页面上,我得到了一个异常(... result = 2153644038)。 出于这个原因,我将我的域添加到响应头的content-security-policy:
//main.js
var { Cc, Ci } = require('chrome');
var observer = {
observe : function(aSubject, aTopic, aData) {
if (aTopic == "http-on-examine-response") {
aSubject.QueryInterface(Ci.nsIHttpChannel);
var csp = aSubject.getResponseHeader("content-security-policy");
if(csp.indexOf('frame-src') > -1) {
var cspParts = csp.split(';');
for (var i=0; i<cspParts.length; i++) {
if(cspParts[i].indexOf('frame-src') > -1) {
cspParts[i] += ' yourdomain.tld';
break;
}
}
aSubject.setResponseHeader("content-security-policy", cspParts.join(';'), false);
}
}
}
};
var observerService = Cc["@mozilla.org/observer-service;1"].getService(Ci.nsIObserverService);
observerService.addObserver(observer, "http-on-examine-response", false);
//content-script.js
iframe.src = yourdomain.tld/...
编辑 :FF审核员可能拒绝此代码:“出于安全原因,不允许修改'content-security-policy'。”
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.