繁体   English   中英

Firefox Addon SDK:将插件文件加载到iframe中

[英]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和父文档之间进行通信(您需要附加内容脚本并使用portpostMessage )。

编辑:更改了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元素,但不能加载XMLHttpRequestWorker 对于后者,仍然存在跨源限制并且引发安全性错误:在XMLHttpRequest情况下“访问受限制的URI被拒绝”,并且“操作是不安全的”。 Worker
相反,在Chrome下,允许使用XMLHttpRequestweb_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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM