commit 45184e903fd682f6eef5a44b6fa44df86a0dbc9f
Author: Arthur Edelstein <arthuredelstein(a)gmail.com>
Date: Sun Mar 5 23:50:15 2017 -0800
Bug 21547: Fix circuit display under e10s
---
src/chrome/content/tor-circuit-display.js | 70 +++++++++++++++++++++----------
1 file changed, 48 insertions(+), 22 deletions(-)
diff --git a/src/chrome/content/tor-circuit-display.js b/src/chrome/content/tor-circuit-display.js
index 14e5e8e..b5c24f8 100644
--- a/src/chrome/content/tor-circuit-display.js
+++ b/src/chrome/content/tor-circuit-display.js
@@ -26,7 +26,7 @@ let createTorCircuitDisplay = (function () {
"use strict";
// Mozilla utilities
-const Cu = Components.utils;
+const { Cu : utils , Ci : interfaces } = Components.utils;
Cu.import("resource://gre/modules/Services.jsm");
Cu.import("resource://gre/modules/Task.jsm");
@@ -34,7 +34,7 @@ Cu.import("resource://gre/modules/Task.jsm");
let { controller } = Cu.import("resource://torbutton/modules/tor-control-port.js", {});
// Utility functions
-let { bindPrefAndInit } = Cu.import("resource://torbutton/modules/utils.js", {});
+let { bindPrefAndInit, observe } = Cu.import("resource://torbutton/modules/utils.js", {});
// Make the TorButton logger available.
let logger = Cc["@torproject.org/torbutton-logger;1"]
@@ -47,7 +47,10 @@ let logger = Cc["@torproject.org/torbutton-logger;1"]
let credentialsToNodeDataMap = {},
// A mutable map that reports `true` for IDs of "mature" circuits
// (those that have conveyed a stream).
- knownCircuitIDs = {};
+ knownCircuitIDs = {},
+ // A mutable map that records the SOCKS credentials for the
+ // latest channels for each browser.
+ browserToCredentialsMap = new Map();
// __trimQuotes(s)__.
// Removes quotation marks around a quoted string.
@@ -154,6 +157,42 @@ let collectIsolationData = function (aController, updateUI) {
}).then(null, Cu.reportError));
};
+// __browserForChannel(channel)__.
+// Returns the browser that loaded a given channel.
+let browserForChannel = function (channel) {
+ if (!channel) return null;
+ let chan = channel.QueryInterface(Ci.nsIChannel);
+ let callbacks = chan.notificationCallbacks;
+ if (!callbacks) return null;
+ let loadContext;
+ try {
+ loadContext = callbacks.getInterface(Ci.nsILoadContext);
+ } catch (e) {
+ // Ignore
+ return null;
+ }
+ if (!loadContext) return null;
+ return loadContext.topFrameElement;
+};
+
+// __collectBrowserCredentials()__.
+// Starts observing http channels. Each channel's proxyInfo
+// username and password is recorded for the channel's browser.
+let collectBrowserCredentials = function () {
+ return observe("http-on-modify-request", chan => {
+ try {
+ let proxyInfo = chan.QueryInterface(Ci.nsIProxiedChannel).proxyInfo;
+ let browser = browserForChannel(chan);
+ if (browser && proxyInfo) {
+ browserToCredentialsMap.set(browser, [proxyInfo.username,
+ proxyInfo.password]);
+ }
+ } catch (e) {
+ logger.eclog(3, `Error collecting browser credentials: ${e.message}, ${chan.URI.spec}`);
+ }
+ });
+};
+
// ## User interface
// __torbuttonBundle__.
@@ -221,24 +260,6 @@ let nodeLines = function (nodeData) {
return result;
};
-// __getSOCKSCredentials(browser)__.
-// Reads the SOCKS credentials for the corresponding browser object.
-let getSOCKSCredentialsForBrowser = function (browser) {
- if (browser === null) return null;
- let docShell = browser.docShell;
- if (docShell === null) return null;
- let channel = docShell.currentDocumentChannel;
- if (channel === null) return null;
- if (channel instanceof Ci.nsIMultiPartChannel) {
- channel = channel.baseChannel;
- }
- if (channel === null) return null;
- if (!(channel instanceof Ci.nsIProxiedChannel)) return null;
- let proxyInfo = channel.proxyInfo;
- if (proxyInfo === null) return null;
- return [proxyInfo.username, proxyInfo.password];
-};
-
// __onionSiteRelayLine__.
// When we have an onion site, we simply show the word '(relay)'.
let onionSiteRelayLine = "<li class='relay'>(" + uiString("relay") + ")</li>";
@@ -249,7 +270,7 @@ let onionSiteRelayLine = "<li class='relay'>(" + uiString("relay") + ")</li>";
let updateCircuitDisplay = function () {
let selectedBrowser = gBrowser.selectedBrowser;
if (selectedBrowser) {
- let credentials = getSOCKSCredentialsForBrowser(selectedBrowser),
+ let credentials = browserToCredentialsMap.get(selectedBrowser),
nodeData = null;
if (credentials) {
let [SOCKS_username, SOCKS_password] = credentials;
@@ -319,12 +340,16 @@ let syncDisplayWithSelectedTab = (function() {
let setupDisplay = function (ipcFile, host, port, password, enablePrefName) {
let myController = null,
stopCollectingIsolationData = null,
+ stopCollectingBrowserCredentials = null,
stop = function() {
syncDisplayWithSelectedTab(false);
if (myController) {
if (stopCollectingIsolationData) {
stopCollectingIsolationData();
}
+ if (stopCollectingBrowserCredentials) {
+ stopCollectingBrowserCredentials();
+ }
myController = null;
}
},
@@ -340,6 +365,7 @@ let setupDisplay = function (ipcFile, host, port, password, enablePrefName) {
});
syncDisplayWithSelectedTab(true);
stopCollectingIsolationData = collectIsolationData(myController, updateCircuitDisplay);
+ stopCollectingBrowserCredentials = collectBrowserCredentials();
}
};
try {