admin管理员组文章数量:1287527
I want to load a resource://
link, respectively a local file from my Firefox addon into an iframe
in a web page.
The reason is, that the resource should be visually embedded into the web page while not giving the website access to it's DOM for security reasons.
The issue has been discussed in various places in the past, e.g. here (without solution): .cgi?id=792479
As most of the postings are rather old, I want to ask, if in the meantime there are any new solutions or workarounds.
I want to load a resource://
link, respectively a local file from my Firefox addon into an iframe
in a web page.
The reason is, that the resource should be visually embedded into the web page while not giving the website access to it's DOM for security reasons.
The issue has been discussed in various places in the past, e.g. here (without solution): https://bugzilla.mozilla/show_bug.cgi?id=792479
As most of the postings are rather old, I want to ask, if in the meantime there are any new solutions or workarounds.
Share Improve this question asked Jan 13, 2014 at 0:27 Patrick GreenPatrick Green 1879 bronze badges3 Answers
Reset to default 11I think I suggested in the bug or in the ML of jetpack a terrible workaround, that basically is convert your resource://
in a data:
url (using data.load
to load the HTML content, and then encode and append as prefix, so something like that should works:
/* 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/en-US/docs/Web/HTML/Element/iframe
iframe.contentWindow.location.href = 'data:text/html;charset=utf-8,' + self.options.content;
It's a workaround of course, and I hope that the bug you mentioned will be fixed soon. Notice that in this way you cannot municate directly from the iframe to the parent's document, but it means also that you can't do the way around, that is what you want to prevent.
Of course, you can still use the add-on code to municate between your iframe and the parent's document (you need to attach content scripts and use port
and postMessage
).
Edit: changed the way the url is set, otherwise getting the src
attribute from the parent's document is still possible, and contains whole HTML.
I used a solution proposed here.
It is implemented by creating a special protocol that is handled by your Firefox addon, which in turn requests the resources from its folder.
Note that in case the resource folder may contain something non-public then I would add additional checks to allow only these resources that really are intended to be web-accessible.
The custom-protocol code attached to the post mentioned above is 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/xp');
var { Cc, Ci, Cr } = require('chrome');
var self = require("sdk/self");
var resourceProtocolHandler = Cc["@mozilla/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/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/network/protocol;1?name=" + scheme,
Component: AddonProtocolHandler
});
exports.url = function(url) {
return self.data.url(url).replace("resource://", scheme + "://");
};
Additional note: for page
scripts (not content
scripts) this custom protocol helps in loading an iframe
and other HTML elements, but not in loading a XMLHttpRequest
or Worker
. For the latter, still cross-origin restrictions apply and a security error is raised: "Access to restricted URI denied" in case of XMLHttpRequest
, and "The operation is insecure." for Worker
.
In contrast, under Chrome the XMLHttpRequest
to web_accessible_resources
is permitted. Worker
does not implement access to web_accessible_resources
under Chrome either.
BUT for Workers
you can use this custom-protocol url for importScripts
method. Using that you can also work around the problem of loading custom resources into Workers
. This code works also in Chrome, as an alternative to using 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);
I'm using zer0's idea. However, on pages with a content-security-policy I got an exception (...result = 2153644038). For that reason, I add my domain to the content-security-policy of the response header:
//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/observer-service;1"].getService(Ci.nsIObserverService);
observerService.addObserver(observer, "http-on-examine-response", false);
//content-script.js
iframe.src = yourdomain.tld/...
EDIT: This code might be rejected by a FF reviewer with: "Modifying 'content-security-policy' is not allowed for security reasons."
本文标签: javascriptFirefox Addon SDK Loading addon file into iframeStack Overflow
版权声明:本文标题:javascript - Firefox Addon SDK: Loading addon file into iframe - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1741259911a2367416.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论