[tor-commits] [torbutton/master] Bug 15086: Handle RTL text in Tor circuit display

gk at torproject.org gk at torproject.org
Thu Mar 12 08:38:33 UTC 2015


commit 6d0c5e64ce8e104e3f9bfe648356a4f40fdde404
Author: Arthur Edelstein <arthuredelstein at 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.
+                          " &#x202D; (" + (ip || uiString("ip_unknown")) + ")&#x202C;"));
   }
-  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%;
+}



More information about the tor-commits mailing list