commit aeb53cde3f5765e8c5e7062afe9dba5b3fc68b50
Author: Arthur Edelstein <arthuredelstein(a)gmail.com>
Date: Mon Nov 3 13:38:48 2014 -0800
fixup! Bug #8641: TorButton popup menu that displays current Tor circuit
---
src/chrome/content/tor-circuit-display.js | 1 +
src/modules/tor-control-port.js | 52 +++++++++++++++++++----------
2 files changed, 36 insertions(+), 17 deletions(-)
diff --git a/src/chrome/content/tor-circuit-display.js b/src/chrome/content/tor-circuit-display.js
index 5f4d8bf..3a1fed8 100644
--- a/src/chrome/content/tor-circuit-display.js
+++ b/src/chrome/content/tor-circuit-display.js
@@ -41,6 +41,7 @@ let regionBundle = Services.strings.createBundle(
// Convert a country code to a localized country name.
// Example: `'de'` -> `'Deutschland'` in German locale.
let localizedCountryNameFromCode = function (countryCode) {
+ if (typeof(countryCode) === "undefined") return "";
try {
return regionBundle.GetStringFromName(countryCode.toLowerCase());
} catch (e) {
diff --git a/src/modules/tor-control-port.js b/src/modules/tor-control-port.js
index 2f993d7..855b34b 100644
--- a/src/modules/tor-control-port.js
+++ b/src/modules/tor-control-port.js
@@ -14,12 +14,23 @@
/* jshint esnext: true */
/* jshint -W097 */
-/* global Components, console */
+/* global Components, console, Services */
"use strict";
// ### Mozilla Abbreviations
let {classes: Cc, interfaces: Ci, results: Cr, Constructor: CC, utils: Cu } = Components;
+// ### Import Mozilla Services
+Cu.import("resource://gre/modules/Services.jsm");
+
+// ## torbutton logger
+let logger = Cc["@torproject.org/torbutton-logger;1"]
+ .getService(Components.interfaces.nsISupports).wrappedJSObject,
+ log = x => logger.eclog(3, x);
+
+// ### announce this file
+log("Loading tor-control-port.js\n");
+
// ## io
// I/O utilities namespace
let io = io || {};
@@ -30,12 +41,12 @@ let io = io || {};
io.asyncSocketStreams = function (host, port) {
let socketTransportService = Cc["@mozilla.org/network/socket-transport-service;1"]
.getService(Components.interfaces.nsISocketTransportService),
- BLOCKING = Ci.nsITransport.OPEN_BLOCKING,
UNBUFFERED = Ci.nsITransport.OPEN_UNBUFFERED,
- // Create an instance of a socket transport.
+ // Create an instance of a socket transport.
socketTransport = socketTransportService.createTransport(null, 0, host, port, null),
- // Open unbuffered synchronous outputStream.
- outputStream = socketTransport.openOutputStream(BLOCKING | UNBUFFERED, 1, 1),
+ // Open unbuffered asynchronous outputStream.
+ outputStream = socketTransport.openOutputStream(UNBUFFERED, 1, 1)
+ .QueryInterface(Ci.nsIAsyncOutputStream),
// Open unbuffered asynchronous inputStream.
inputStream = socketTransport.openInputStream(UNBUFFERED, 1, 1)
.QueryInterface(Ci.nsIAsyncInputStream);
@@ -81,21 +92,28 @@ io.pumpInputStream = function (inputStream, onInputData, onError) {
// socket.write(text) and socket.close(). onError will be passed the error object
// whenever a write fails.
io.asyncSocket = function (host, port, onInputData, onError) {
- let [inputStream, outputStream] = io.asyncSocketStreams(host, port);
+ let [inputStream, outputStream] = io.asyncSocketStreams(host, port),
+ pendingWrites = [];
// Run an input stream pump to send incoming data to the onInputData callback.
io.pumpInputStream(inputStream, onInputData, onError);
+ // Return the "socket object" as described.
return {
// Write a message to the socket.
write : function(aString) {
- try {
- outputStream.write(aString, aString.length);
- // console.log(aString);
- } catch (err) {
- // This write() method is not necessarily called by a callback,
- // but we pass any thrown errors to onError to ensure the socket
- // error handling uses a consistent single path.
- onError(err);
- }
+ pendingWrites.push(aString);
+ outputStream.asyncWait(
+ // Implement an nsIOutputStreamCallback:
+ { onOutputStreamReady : function () {
+ let totalString = pendingWrites.join("");
+ try {
+ outputStream.write(totalString, totalString.length);
+ log("wrote: " + aString + "\n");
+ } catch (err) {
+ onError(err);
+ }
+ pendingWrites = [];
+ } },
+ 0, 0, Services.tm.currentThread);
},
// Close the socket.
close : function () {
@@ -146,7 +164,7 @@ io.onLineFromOnMessage = function (onMessage) {
pendingLines = [];
// Pass multiline message to onMessage.
onMessage(message);
- // console.log(message);
+ //log(message);
}
};
};
@@ -241,7 +259,7 @@ io.controlSocket = function (host, port, password, onError) {
// Log in to control port.
sendCommand("authenticate " + (password || ""));
// Activate needed events.
- sendCommand("setevents stream circ");
+ sendCommand("setevents circ");
return { close : socket.close, sendCommand : sendCommand,
addNotificationCallback : notificationDispatcher.addCallback,
removeNotificationCallback : notificationDispatcher.removeCallback };