Add initial working implementation of the ccnx protocol handler for Firefox. The extension is ccnxProtocol.xpi.
diff --git a/js/NDNSocketTransportService.js b/js/NDNSocketTransportService.js
new file mode 100644
index 0000000..d4a2634
--- /dev/null
+++ b/js/NDNSocketTransportService.js
@@ -0,0 +1,111 @@
+/* Implement getAsync and putAsync used by NDN using nsISocketTransportService.
+   This is used inside Firefox XPCOM modules.
+ */
+
+// Assume already imported the following:
+// Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
+// Components.utils.import("resource://gre/modules/NetUtil.jsm");
+
+/** Convert outputHex to binary, send to host:port and call hexListener.onReceivedHexData(hexData).
+ */
+function getAsync(host, port, outputHex, hexListener) {
+	var binaryListener = {
+		onReceivedData : function(data) {
+			hexListener.onReceivedHexData(DataUtils.stringToHex(data));
+		}
+	}
+
+    readAllFromSocket(host, port, DataUtils.hexToRawString(outputHex), binaryListener);
+}
+
+/** Send outputData to host:port, read the entire response and call listener.onReceivedData(data).
+    Code derived from http://stackoverflow.com/questions/7816386/why-nsiscriptableinputstream-is-not-working .
+ */
+function readAllFromSocket(host, port, outputData, listener) {
+	var transportService = Components.classes["@mozilla.org/network/socket-transport-service;1"].getService
+	(Components.interfaces.nsISocketTransportService);
+	var pump = Components.classes["@mozilla.org/network/input-stream-pump;1"].createInstance
+	(Components.interfaces.nsIInputStreamPump);
+	var transport = transportService.createTransport(null, 0, host, port, null);
+	var outStream = transport.openOutputStream(1, 0, 0);
+	outStream.write(outputData, outputData.length);
+	outStream.flush();
+	var inStream = transport.openInputStream(0, 0, 0);
+	var dataListener = {
+		data: "",
+		calledOnReceivedData: false,
+		
+		onStartRequest: function (request, context) {
+		},
+		onStopRequest: function (request, context, status) {
+			inStream.close();
+			outStream.close();
+			if (!this.calledOnReceivedData) {
+				this.calledOnReceivedData = true;
+				listener.onReceivedData(this.data);
+			}
+		},
+		onDataAvailable: function (request, context, _inputStream, offset, count) {
+			try {
+				// Ignore _inputStream and use inStream.
+				// Use readInputStreamToString to handle binary data.
+				this.data += NetUtil.readInputStreamToString(inStream, count);
+				
+				// TODO: Don't know why, but we never receive onStopRequest, assume we have
+				//   all the data and force it now.
+				this.onStopRequest();
+			} catch (ex) {
+				dump("onDataAvailable exception: " + ex + "\n");
+			}
+		}
+    };
+	
+	pump.init(inStream, -1, -1, 0, 0, true);
+    pump.asyncRead(dataListener, null);
+}
+
+
+// TODO: This should be moved to the main NDN.js when we agree on how to do non-blocking get.
+// For now, assume this is included after NDN.js and modify it.
+/** Encode message as an Interest, send it to host:port, read the entire response and call
+      listener.onReceivedContentObject(contentObject).
+ */
+NDN.prototype.getAsync = function(message, listener) {
+	if (this.host != null && this.port != null) {
+		var output ='';
+		message = message.trim();
+		if(message==null || message =="" ){
+			dump('INVALID INPUT TO GET\n');
+			return null;
+		}
+		
+		int = new Interest(new Name(message));
+		int.InterestLifetime = 4200;
+		var outputHex = encodeToHexInterest(int);
+		
+		var hexListener = {
+			onReceivedHexData : function(result) {
+				if (LOG>0) dump('BINARY RESPONSE IS ' + result + '\n');
+				
+				if (result == null || result == undefined || result =="" )
+					listener.onReceivedContentObject(null);
+				else {
+					var co = decodeHexContentObject(result);
+					
+					if(LOG>2) {
+						dump('DECODED CONTENT OBJECT\n');
+						dump(co);
+						dump('\n');
+					}
+					
+					listener.onReceivedContentObject(co);
+				}
+			}
+		}
+		return getAsync(this.host, this.port, outputHex, hexListener);
+	}
+	else {
+		dump('ERROR host OR port NOT SET\n');
+	}
+}
+