Add initial working implementation of the ccnx protocol handler for Firefox. The extension is ccnxProtocol.xpi.
diff --git a/js/ccnxProtocol/modules/ContentChannel.jsm b/js/ccnxProtocol/modules/ContentChannel.jsm
new file mode 100644
index 0000000..2dfb1ed
--- /dev/null
+++ b/js/ccnxProtocol/modules/ContentChannel.jsm
@@ -0,0 +1,94 @@
+var EXPORTED_SYMBOLS = ["ContentChannel"];
+
+const Cc = Components.classes;
+const Ci = Components.interfaces;
+const Cr = Components.results;
+
+Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
+
+/** Create an nsIChannel where asyncOpen calls requestContent(contentListener). When the content
+ is available, call contentListener.onReceivedContent(content, contentType, contentCharset).
+ The content is sent to the listener passed to asyncOpen.
+ */
+function ContentChannel(uri, requestContent) {
+ this.requestContent = requestContent;
+
+ this.done = false;
+
+ this.name = uri;
+ this.loadFlags = 0;
+ this.loadGroup = null;
+ this.status = 200;
+
+ // We don't know these yet.
+ this.contentLength = -1;
+ this.contentType = null;
+ this.contentCharset = null;
+ this.URI = uri;
+ this.originalURI = uri;
+ this.owner = null;
+ this.notificationCallback = null;
+ this.securityInfo = null;
+}
+
+ContentChannel.prototype = {
+ QueryInterface: function(aIID) {
+ if (aIID.equals(Ci.nsISupports))
+ return this;
+
+ if (aIID.equals(Ci.nsIRequest))
+ return this;
+
+ if (aIID.equals(Ci.nsIChannel))
+ return this;
+
+ throw Cr.NS_ERROR_NO_INTERFACE;
+ },
+
+ isPending: function() {
+ return !this.done;
+ },
+
+ cancel: function(aStatus){
+ this.status = aStatus;
+ this.done = true;
+ },
+
+ suspend: function(aStatus){
+ this.status = aStatus;
+ },
+
+ resume: function(aStatus){
+ this.status = aStatus;
+ },
+
+ open: function() {
+ throw Cr.NS_ERROR_NOT_IMPLEMENTED;
+ },
+
+ asyncOpen: function(aListener, aContext) {
+ var thisContentChannel = this;
+ var contentListener = {
+ onReceivedContent : function(content, contentType, contentCharset) {
+ thisContentChannel.contentLength = content.length;
+ thisContentChannel.contentType = contentType;
+ thisContentChannel.contentCharset = contentCharset;
+
+ // Call aListener immediately to send all the content.
+ aListener.onStartRequest(thisContentChannel, aContext);
+
+ var pipe = Cc["@mozilla.org/pipe;1"].createInstance(Ci.nsIPipe);
+ pipe.init(true, true, 0, 0, null);
+ pipe.outputStream.write(content, content.length);
+ pipe.outputStream.close();
+
+ aListener.onDataAvailable(thisContentChannel, aContext, pipe.inputStream, 0, content.length);
+
+ thisContentChannel.done = true;
+ aListener.onStopRequest(thisContentChannel, aContext, thisContentChannel.status);
+ }
+ };
+
+ this.requestContent(contentListener);
+ }
+};