[英]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.