簡體   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