Skip to content

Instantly share code, notes, and snippets.

@caisui
Created September 14, 2012 11:58
Show Gist options
  • Select an option

  • Save caisui/3721530 to your computer and use it in GitHub Desktop.

Select an option

Save caisui/3721530 to your computer and use it in GitHub Desktop.
const {classes: Cc, interfaces: Ci, utils: Cu} = Components;
const self = this;
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
Cu.import("resource://gre/modules/Services.jsm");
XPCOMUtils.defineLazyGetter(this, "protocol", function () {
var url = "resource://sourceless/protocol.js";
Cu.unload(url);
var temp = {};
Cu.import(url, temp);
return temp;
});
function startup(data, reason) {
var resHandler = Services.io.getProtocolHandler("resource").QueryInterface(Ci.nsIResProtocolHandler);
resHandler.setSubstitution("sourceless", Services.io.newURI("components/", null, data.resourceURI));
//Components.manager.addBootstrappedManifestLocation(data.installPath);
protocol.startup();
Cu.reportError("ok");
try {
var uri = "test:resource://sourceless/test.js";
// xxx:
// 1. nsINestedURInsINested URI.nestURI instanceof nsIFileURI
// 2. URI scheme is chorome
Services.scriptloader.loadSubScript(uri + "?" + Date.now(), new Object);
Cu.unload(uri);
// xxx: now cannot support
// channel.URI instanceof nsIJARURI or nsIFileURI
Cu.import(uri, new Object);
} catch (ex) {Cu.reportError(ex);}
}
function shutdown(data, reason) {
protocol.shutdown();
}
function install(data, reason) {
}
function uninstall(data, reason) {
}
<?xml version="1.0"?>
<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:em="http://www.mozilla.org/2004/em-rdf#">
<Description about="urn:mozilla:install-manifest">
<!-- properties -->
<em:id>[email protected]</em:id>
<em:name>sourceless</em:name>
<em:version>0.0.1</em:version>
<em:creator>caisui</em:creator>
<em:bootstrap>true</em:bootstrap>
<em:optionsURL></em:optionsURL>
<em:targetApplication>
<Description>
<em:id>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</em:id>
<em:minVersion>8.0</em:minVersion>
<em:maxVersion>99.*</em:maxVersion>
</Description>
</em:targetApplication>
</Description>
</RDF>
src= install.rdf Makefile $(shell find . \( -name '*.js' -or -name chrome.manifest \))
output=sourceless.xpi
xpi: $(src)
zip $(output) -r $(src)
var EXPORTED_SYMBOLS = ["startup", "shutdown"];
const Ci = Components.interfaces, Cc = Components.classes, Cu = Components.utils;
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
Cu.import("resource://gre/modules/Services.jsm");
XPCOMUtils.defineLazyGetter(this, "Cm", function () {
return Components.manager.QueryInterface(Ci.nsIComponentRegistrar);
});
function Protocol() {
this.wrappedJSObject = this;
}
var P = Protocol.prototype;
var schema = "test";
var contractID = P.contractID = "@mozilla.org/network/protocol;1?name=" + schema;
var classID = P.classID = Components.ID("{A0D7DF10-2D96-48ae-9CC7-2DB06AFD59A5}");
var classDescription = P.classDescription = "sourceless orz";
P.QueryInterface = XPCOMUtils.generateQI([Components.interfaces.nsIProtocolHandler]);
P.scheme = schema;
P.defaultPort = -1,
P.allowPorta = function (port, scheme) false;
P.protocolFlags = let (i = Ci.nsIProtocolHandler)
i.URI_IS_LOCAL_RESOURCE
| i.URI_IS_UI_RESOURCE;
P.newURI = function newURI(spec, charset, baseURI) {
var uri = Services.io.newURI(spec.substr(this.scheme.length + 1), charset, null);
if (uri.scheme === "chrome") {
uri = Cc["@mozilla.org/chrome/chrome-registry;1"]
.getService(Ci.nsIChromeRegistry)
.convertChromeURL(uri);
}
var nest = Cc["@mozilla.org/network/util;1"].getService(Ci.nsINetUtil).newSimpleNestedURI(uri);
nest.spec = spec;
return nest;
};
P.newChannel = function newChannel(uri) {
if (uri instanceof Ci.nsINestedURI) {
try {
var nestURI = Services.io.newURI(uri.path, uri.originCharset, null);
var channel = Services.io.newChannelFromURI(nestURI);
var stream = Cc["@mozilla.org/scriptableinputstream;1"]
.createInstance(Ci.nsIScriptableInputStream);
var cstream = channel.open();
stream.init(cstream);
var text = stream.read(-1);
stream.close();
cstream.close();
//xxx:
//text = convert(text);
//text += "\n1+1;";
var dataURI = Services.io.newURI("data:text/javascript;encoding=UTF-8," + encodeURIComponent(text), null, null);
channel = Services.io.newChannelFromURI(dataURI);
channel.originalURI = nestURI;
return channel;
} catch (ex) { Cu.reportError(ex); }
}
throw new Error;
};
delete P;
var factory = {
self: null,
QueryInterface: function(iid) {
if (iid.equals(Ci.nsISupports) || iid.equals(Ci.nsIFactory))
return this;
throw Cr.NS_ERROR_NO_AGGREGATION;
},
//xxx: outer?
createInstance: function (outer, iid) {
if (outer != null) {
throw Cr.NS_ERROR_NO_AGGREGATION;
}
return this.self || (this.self = (new Protocol).QueryInterface(iid));
},
};
function startup() {
Cm.registerFactory(classID, classDescription, contractID, factory);
}
function shutdown() {
try {
// xxx: processNextEvent が 無いと 失敗することがある
Services.tm.mainThread.processNextEvent(true);
Cm.unregisterFactory(classID, factory);
} catch (ex) { Cu.reportError(ex); }
Cu.reportError("unregsiter factory");
}
Components.utils.reportError((function () {}).toString());
@teramako
Copy link

問題は以下のエラーでしょうか?

時刻: 2012/09/14 23:48:05
エラー: [Exception... "Component returned failure code: 0x80004002 (NS_NOINTERFACE) [nsIXPCComponents_Utils.import]"  nsresult: "0x80004002 (NS_NOINTERFACE)"  location: "JS frame :: resource:///modules/XPIProvider.jsm -> jar:file:///C:/Documents%20and%20Settings/teramako/Application%20Data/Mozilla/Firefox/Profiles/zyi1wr9j.default/extensions/[email protected]!/bootstrap.js :: startup :: line 33"  data: no]
ソースファイル: resource:///modules/XPIProvider.jsm -> jar:file:///C:/Documents%20and%20Settings/teramako/Application%20Data/Mozilla/Firefox/Profiles/zyi1wr9j.default/extensions/[email protected]!/bootstrap.js
行: 34

Vimperatorから以下を実行しても同じようなエラーが出たので、dataURIではダメなのかもしれません。

Cu.import('data:application/javascript,'+encodeURIComponent('var EXPORTED_SYMBOLS=["test"]; var test = {};'), {})

Cu.importの実装を見てみました。
http://mxr.mozilla.org/mozilla-central/source/js/xpconnect/loader/mozJSComponentLoader.cpp#1064

引数のaLocationのURLからローカルファイルのオブジェクトへ変換しているように思われます。その辺りで失敗してNS_NOINTERFACEが出ているように思います。

@caisui
Copy link
Author

caisui commented Sep 14, 2012

ありがとうございます。
import は、dataURIでない方法で渡さないと無理でそうですね。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment