Я использовал a solution proposed here.
Он реализуется путем создания специального протокола, который обрабатывается вашим аддоном Firefox, который, в свою очередь, запрашивает ресурсы из своей папки.
Обратите внимание, что если папка ресурса может содержать что-то непубличное, я бы добавил дополнительные проверки, чтобы разрешить доступ только к этим ресурсам, которые действительно предназначены для веб-доступа.
Код на заказ протокол прилагается к сообщению упомянутого выше available here:
/*
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
. Для последнего применяются ограничения по кросс-началу и возникает ошибка безопасности: «Доступ к ограниченному URI отклонен» в случае XMLHttpRequest
и «Операция небезопасна». для Worker
.
Напротив, под Хром допускается XMLHttpRequest
до web_accessible_resources
. Worker
не реализует доступ к web_accessible_resources
под Chrome.
BUT для 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);
Спасибо. Не может ли родительский документ восстановить доступ к содержимому iframe, удалив атрибут sandbox? –
** Редактировать: ** Нет, не может. Изменения атрибута «песочница» применяются только при перезагрузке страницы. –
Со всеми последними усовершенствованиями API Jetpack, является ли это все еще лучшей техникой, доступной для работы этой функции iframe? – NoR