commit 6d0c5e64ce8e104e3f9bfe648356a4f40fdde404 Author: Arthur Edelstein arthuredelstein@gmail.com Date: Sun Mar 1 17:04:48 2015 -0800
Bug 15086: Handle RTL text in Tor circuit display
Also fixes #13704 (circuit display now accomodates more than 3 relays). --- src/chrome/content/popup.xul | 56 +++++++-------- src/chrome/content/tor-circuit-display.js | 41 +++++++---- src/chrome/skin/tor-circuit-display.css | 106 +++++++++++++++++++++++++++++ 3 files changed, 156 insertions(+), 47 deletions(-)
diff --git a/src/chrome/content/popup.xul b/src/chrome/content/popup.xul index e0c1f74..6511b6c 100644 --- a/src/chrome/content/popup.xul +++ b/src/chrome/content/popup.xul @@ -1,18 +1,21 @@ <?xml version="1.0"?> <?xml-stylesheet href="chrome://torbutton/skin/torbutton.css" type="text/css"?> +<?xml-stylesheet href="chrome://torbutton/skin/tor-circuit-display.css" type="text/css"?>
<!DOCTYPE overlay SYSTEM "chrome://torbutton/locale/torbutton.dtd">
<overlay id="torbutton-popup-overlay" xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
- <stringbundleset id="torbutton-stringbundleset"> - <stringbundle id="torbutton-bundle" src="chrome://torbutton/locale/torbutton.properties"/> - </stringbundleset> - <panel id="torbutton-context-menu" onpopupshowing="torbutton_check_protections();" titlebar="normal" noautohide="true" - anchor="torbutton-button" position="after_start" > - <hbox align="start"> - <vbox> + <stringbundleset id="torbutton-stringbundleset"> + <stringbundle id="torbutton-bundle" src="chrome://torbutton/locale/torbutton.properties"/> + </stringbundleset> + <panel id="torbutton-context-menu" + onpopupshowing="torbutton_check_protections();" + titlebar="normal" noautohide="true" + anchor="torbutton-button" position="after_start" > + <hbox align="start"> + <vbox> <menuitem id="torbutton-new-identity" label="&torbutton.context_menu.new_identity;" accesskey="&torbutton.context_menu.new_identity_key;" @@ -45,29 +48,18 @@ accesskey="&torbutton.context_menu.downloadUpdate.key;" insertafter="context-stop" oncommand="torbutton_check_for_update()"/> - </vbox> - <vbox> - <!-- The following SVG is used to display a Tor circuit diagram for the current tab. - It is not displayed unless activated by tor-circuit-display.js. --> - <svg xmlns="http://www.w3.org/2000/svg" version="1.1" baseProfile="full" - width="290" height="140" id="tor-circuit" style="display:none;"> - <rect x="0" y="0" width="100%" height="100%" fill="#e8f4f4" /> - <text id="title" style="font-size:14px;font-weight:bold;" x="10" y="20" fill="#2c26a7">&torbutton.circuit_display.title;</text> - <text id="domain" style="font-size:13px;" x="10" y="38" fill="black">(trac.torproject.org):</text> - <rect x="18.5" width="3" y="56" height="64" fill="#4d363a" stroke-width="0"/> - <circle class="node-circle" cx="20" cy="56" r="4" /> - <text class="node-text" x="32" y="56">This Browser</text> - <circle class="node-circle" cx="20" cy="72" r="4" /> - <text class="node-text" x="32" y="72">Test123 (54.67.87.34)</text> - <circle class="node-circle" cx="20" cy="88" r="4" /> - <text class="node-text" x="32" y="88">TestABC (121.4.56.67)</text> - <circle class="node-circle" cx="20" cy="104" r="4" /> - <text class="node-text" x="32" y="104">TestXYZ (74.3.30.9)</text> - <circle class="node-circle" cx="20" cy="120" r="4" /> - <text class="node-text" x="32" y="120">Internet</text> - </svg> - </vbox> - </hbox> - </panel> - + </vbox> + <vbox id="circuit-display-container"> + <div id="circuit-display" xmlns="http://www.w3.org/1999/xhtml" dir="auto"> + <p id="title">&torbutton.circuit_display.title;</p> + <p id="domain">(example.com):</p> + <ul id="circuit-nodes" dir="auto"> + <li>example A</li> + <li>example B</li> + <li>example C</li> + </ul> + </div> + </vbox> + </hbox> + </panel> </overlay> diff --git a/src/chrome/content/tor-circuit-display.js b/src/chrome/content/tor-circuit-display.js index bcda03a..fc4da14 100644 --- a/src/chrome/content/tor-circuit-display.js +++ b/src/chrome/content/tor-circuit-display.js @@ -173,26 +173,37 @@ let localizedCountryNameFromCode = function (countryCode) { // __showCircuitDisplay(show)__. // If show === true, makes the circuit display visible. let showCircuitDisplay = function (show) { - document.querySelector("svg#tor-circuit").style.display = show ? + document.getElementById("circuit-display-container").style.display = show ? 'block' : 'none'; };
// __nodeLines(nodeData)__. -// Takes a nodeData array of three items each like +// Takes a nodeData array of node items, each like // `{ ip : "12.34.56.78", country : "fr" }` // and converts each node data to text, as -// `"France (12.34.56.78)"`. +// `"France (12.34.56.78)"`, prepended by "This browser" +// and appended by "Internet". let nodeLines = function (nodeData) { let result = [uiString("this_browser")]; for (let {ip, countryCode, type, bridgeType} of nodeData) { let bridge = type === "bridge"; - result.push((countryCode ? localizedCountryNameFromCode(countryCode) + result.push( + // For each relay, show its apparent host country. + (countryCode ? localizedCountryNameFromCode(countryCode) : uiString("unknown_country")) + - " (" + (bridge ? (uiString("tor_bridge") + - ((bridgeType !== "vanilla") ? (": " + bridgeType) : "")) - : (ip || uiString("ip_unknown"))) + ")"); + (bridge ? + // As we have a bridge, don't show the IP address + // but show the bridge type. + " (" + uiString("tor_bridge") + + ((bridgeType !== "vanilla") ? (": " + bridgeType) : "") + ")" + : + // As we don't have a bridge, show the IP address + // of the node. Use unicode escapes to ensure that + // parentheses behave properly in both left-to-right + // and right-to-left languages. + " ‭ (" + (ip || uiString("ip_unknown")) + ")‬")); } - result[4] = uiString("internet"); + result.push(uiString("internet")); return result; };
@@ -215,7 +226,7 @@ let getSOCKSCredentialsForBrowser = function (browser) { };
// __updateCircuitDisplay()__. -// Updates the Tor circuit display SVG, showing the current domain +// Updates the Tor circuit display, showing the current domain // and the relay nodes for that domain. let updateCircuitDisplay = function () { let selectedBrowser = gBrowser.selectedBrowser; @@ -228,14 +239,14 @@ let updateCircuitDisplay = function () { if (nodeData) { // Update the displayed domain. let domain = credentials.split(":")[0]; - document.querySelector("svg#tor-circuit text#domain").innerHTML = "(" + domain + "):"; + document.getElementById("domain").innerHTML = "(" + domain + "):"; // Update the displayed information for the relay nodes. - let diagramNodes = document.querySelectorAll("svg#tor-circuit text.node-text"), - lines = nodeLines(nodeData); - for (let i = 0; i < diagramNodes.length; ++i) { - let line = lines[i]; - diagramNodes[i].innerHTML = line ? line : ""; + let lines = nodeLines(nodeData), + nodeInnerHTML = ""; + for (let line of lines) { + nodeInnerHTML += "<li>" + line + "</li>"; } + document.getElementById("circuit-nodes").innerHTML = nodeInnerHTML; } } // Only show the Tor circuit if we have credentials and node data. diff --git a/src/chrome/skin/tor-circuit-display.css b/src/chrome/skin/tor-circuit-display.css new file mode 100644 index 0000000..b9d0638 --- /dev/null +++ b/src/chrome/skin/tor-circuit-display.css @@ -0,0 +1,106 @@ +/* +This CSS file is for styling the tor circuit display. It consists of a title, +a domain, and a bulleted list. + +Each bullet in the circuit node list is supposed to represent a Tor circuit node, +and lines drawn between them to represent Tor network inter-relay connections. + +CSS for line between bullets is Derived in part from https://jsfiddle.net/5JP8Q/ + +Color the background to make circuit display distinct from the rest of popup. +*/ + +/* The circuit-display div encloses all other HTML elements. */ +div#circuit-display { + background-color: #e8f4f4; + font-family: Arial; + width: 100%; + height: 100%; + padding: 8px; + /* Magically keep popup menu from clipping div: */ + display: table-cell; +} + +/* Format the title text. */ +div#circuit-display p#title { + font-size: 15px; + font-weight: bold; + color: #2c26a7; + margin: 0; +} + +/* Format the domain text. */ +div#circuit-display p#domain { + font-size: 13px; + color: black; + margin: 4px; +} + +/* Format the circuit node list. */ +ul#circuit-nodes { + font-family: Arial; + font-size: 14px; + margin-top: 8px; + padding-left: 8px; + padding-right: 8px; +} + +/* Hide default bullets, and position pseudoelements (our new bullets) relative + to the list items. */ +ul#circuit-nodes li { + list-style: none; + position:relative; +} + +/* Pad the list item text at left or right to be tastefully + separated from bullets. */ +ul#circuit-nodes li:-moz-dir(ltr) { + padding-left: 18px; +} +ul#circuit-nodes li:-moz-dir(rtl) { + padding-right: 18px; +} + +/* Drawn bullets, centered vertically for each list item. */ +ul#circuit-nodes li:after { + /* bullets */ + content: url("data:image/svg+xml;utf8,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20width%3D%2711%27%20height%3D%2711%27%3E%3Ccircle%20cx%3D%275.5%27%20cy%3D%275.5%27%20r%3D%274%27%20style%3D%27stroke%3A%20%23195021%3B%20stroke-width%3A%202px%3B%20fill%3A%20white%3B%27%2F%3E%3C%2Fsvg%3E"); + position: absolute; + top: 1px; +} + +/* Move the bullets to the far left or right, + depending on text directionality. */ +ul#circuit-nodes li:-moz-dir(ltr):after { + left: 0px; +} +ul#circuit-nodes li:-moz-dir(rtl):after { + right: 0px; +} + +/* Draw a connecting vertical line through the bullets. */ +ul#circuit-nodes li:before { + content: ""; + position: absolute; + border-left: 3px solid #4d363a; + height: 100%; + width: 0px; +} + +/* Position lines through the middle of the bullet. */ +ul#circuit-nodes li:-moz-dir(ltr):before { + left: 4px; +} +ul#circuit-nodes li:-moz-dir(rtl):before { + right: 4px; +} + +/* Shorten the first list item's line so that it starts under the bullet. */ +ul#circuit-nodes li:first-child:before { + top: 50%; +} + +/* Shorten the last list item's line so that it ends under the bullet. */ +ul#circuit-nodes li:last-child:before { + height: 50%; +}