tor-commits
Threads by month
- ----- 2025 -----
- July
- June
- May
- April
- March
- February
- January
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
March 2021
- 17 participants
- 2169 discussions

[tor-browser/tor-browser-78.9.0esr-10.5-1] Bug 25741 - TBA: Disable GeckoNetworkManager
by sysrqb@torproject.org 17 Mar '21
by sysrqb@torproject.org 17 Mar '21
17 Mar '21
commit d785d6ab291489644118d30257410656427d0d21
Author: Matthew Finkel <Matthew.Finkel(a)gmail.com>
Date: Thu Apr 26 22:22:51 2018 +0000
Bug 25741 - TBA: Disable GeckoNetworkManager
The browser should not need information related to the network
interface or network state, tor should take care of that.
---
.../src/main/java/org/mozilla/geckoview/GeckoRuntime.java | 8 ++++++--
1 file changed, 6 insertions(+), 2 deletions(-)
diff --git a/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/GeckoRuntime.java b/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/GeckoRuntime.java
index ed86dcc5c299..f5587dd7e59c 100644
--- a/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/GeckoRuntime.java
+++ b/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/GeckoRuntime.java
@@ -121,7 +121,9 @@ public final class GeckoRuntime implements Parcelable {
mPaused = false;
// Monitor network status and send change notifications to Gecko
// while active.
- GeckoNetworkManager.getInstance().start(GeckoAppShell.getApplicationContext());
+ if (BuildConfig.TOR_BROWSER_VERSION == "") {
+ GeckoNetworkManager.getInstance().start(GeckoAppShell.getApplicationContext());
+ }
}
@OnLifecycleEvent(Lifecycle.Event.ON_PAUSE)
@@ -129,7 +131,9 @@ public final class GeckoRuntime implements Parcelable {
Log.d(LOGTAG, "Lifecycle: onPause");
mPaused = true;
// Stop monitoring network status while inactive.
- GeckoNetworkManager.getInstance().stop();
+ if (BuildConfig.TOR_BROWSER_VERSION == "") {
+ GeckoNetworkManager.getInstance().stop();
+ }
GeckoThread.onPause();
}
}
1
0

[tor-browser/tor-browser-78.9.0esr-10.5-1] Bug 32220: Improve the letterboxing experience
by sysrqb@torproject.org 17 Mar '21
by sysrqb@torproject.org 17 Mar '21
17 Mar '21
commit d3c088c4c7d2abc14e0ca4c84bc6817602e885fe
Author: Richard Pospesel <richard(a)torproject.org>
Date: Mon Oct 28 17:42:17 2019 -0700
Bug 32220: Improve the letterboxing experience
CSS and JS changes to alter the UX surrounding letterboxing. The
browser element containing page content is now anchored to the bottom
of the toolbar, and the remaining letterbox margin is the same color
as the firefox chrome. The letterbox margin and border are tied to
the currently selected theme.
Also adds a 'needsLetterbox' property to tabbrowser.xml to fix a race
condition present when using the 'isEmpty' property. Using 'isEmpty'
as a proxy for 'needsLetterbox' resulted in over-zealous/unnecessary
letterboxing of about:blank tabs.
---
browser/base/content/browser.css | 8 ++
browser/base/content/tabbrowser-tab.js | 9 +++
browser/themes/shared/tabs.inc.css | 6 ++
.../components/resistfingerprinting/RFPHelper.jsm | 94 +++++++++++++++++++---
4 files changed, 105 insertions(+), 12 deletions(-)
diff --git a/browser/base/content/browser.css b/browser/base/content/browser.css
index 808c03e88223..a0b1bf4a8951 100644
--- a/browser/base/content/browser.css
+++ b/browser/base/content/browser.css
@@ -85,6 +85,14 @@ body {
display: none;
}
+
+.browserStack > browser.letterboxing {
+ border-color: var(--chrome-content-separator-color);
+ border-style: solid;
+ border-width : 1px;
+ border-top: none;
+}
+
%ifdef MENUBAR_CAN_AUTOHIDE
#toolbar-menubar[autohide="true"] {
overflow: hidden;
diff --git a/browser/base/content/tabbrowser-tab.js b/browser/base/content/tabbrowser-tab.js
index 183eff1bab86..7f376ab1d122 100644
--- a/browser/base/content/tabbrowser-tab.js
+++ b/browser/base/content/tabbrowser-tab.js
@@ -225,6 +225,15 @@
return true;
}
+ get needsLetterbox() {
+ let browser = this.linkedBrowser;
+ if (isBlankPageURL(browser.currentURI.spec)) {
+ return false;
+ }
+
+ return true;
+ }
+
get lastAccessed() {
return this._lastAccessed == Infinity ? Date.now() : this._lastAccessed;
}
diff --git a/browser/themes/shared/tabs.inc.css b/browser/themes/shared/tabs.inc.css
index b47842af766c..019da6ecf76f 100644
--- a/browser/themes/shared/tabs.inc.css
+++ b/browser/themes/shared/tabs.inc.css
@@ -33,6 +33,12 @@
background-color: #f9f9fa;
}
+/* extend down the toolbar's colors when letterboxing is enabled*/
+#tabbrowser-tabpanels.letterboxing {
+ background-color: var(--toolbar-bgcolor);
+ background-image: var(--toolbar-bgimage);
+}
+
:root[privatebrowsingmode=temporary] #tabbrowser-tabpanels {
/* Value for --in-content-page-background in aboutPrivateBrowsing.css */
background-color: #25003e;
diff --git a/toolkit/components/resistfingerprinting/RFPHelper.jsm b/toolkit/components/resistfingerprinting/RFPHelper.jsm
index 49010d1c8cb1..b906a067fd63 100644
--- a/toolkit/components/resistfingerprinting/RFPHelper.jsm
+++ b/toolkit/components/resistfingerprinting/RFPHelper.jsm
@@ -40,6 +40,7 @@ class _RFPHelper {
// ============================================================================
constructor() {
this._initialized = false;
+ this._borderDimensions = null;
}
init() {
@@ -361,6 +362,24 @@ class _RFPHelper {
});
}
+ getBorderDimensions(aBrowser) {
+ if (this._borderDimensions) {
+ return this._borderDimensions;
+ }
+
+ const win = aBrowser.ownerGlobal;
+ const browserStyle = win.getComputedStyle(aBrowser);
+
+ this._borderDimensions = {
+ top : parseInt(browserStyle.borderTopWidth),
+ right: parseInt(browserStyle.borderRightWidth),
+ bottom : parseInt(browserStyle.borderBottomWidth),
+ left : parseInt(browserStyle.borderLeftWidth),
+ };
+
+ return this._borderDimensions;
+ }
+
_addOrClearContentMargin(aBrowser) {
let tab = aBrowser.getTabBrowser().getTabForBrowser(aBrowser);
@@ -369,9 +388,13 @@ class _RFPHelper {
return;
}
+ // we add the letterboxing class even if the content does not need letterboxing
+ // in which case margins are set such that the borders are hidden
+ aBrowser.classList.add("letterboxing");
+
// We should apply no margin around an empty tab or a tab with system
// principal.
- if (tab.isEmpty || aBrowser.contentPrincipal.isSystemPrincipal) {
+ if (!tab.needsLetterbox || aBrowser.contentPrincipal.isSystemPrincipal) {
this._clearContentViewMargin(aBrowser);
} else {
this._roundContentView(aBrowser);
@@ -539,10 +562,29 @@ class _RFPHelper {
// Calculating the margins around the browser element in order to round the
// content viewport. We will use a 200x100 stepping if the dimension set
// is not given.
- let margins = calcMargins(containerWidth, containerHeight);
+
+ const borderDimensions = this.getBorderDimensions(aBrowser);
+ const marginDims = calcMargins(containerWidth, containerHeight - borderDimensions.top);
+
+ let margins = {
+ top : 0,
+ right : 0,
+ bottom : 0,
+ left : 0,
+ };
+
+ // snap browser element to top
+ margins.top = 0;
+ // and leave 'double' margin at the bottom
+ margins.bottom = 2 * marginDims.height - borderDimensions.bottom;
+ // identical margins left and right
+ margins.right = marginDims.width - borderDimensions.right;
+ margins.left = marginDims.width - borderDimensions.left;
+
+ const marginStyleString = `${margins.top}px ${margins.right}px ${margins.bottom}px ${margins.left}px`;
// If the size of the content is already quantized, we do nothing.
- if (aBrowser.style.margin == `${margins.height}px ${margins.width}px`) {
+ if (aBrowser.style.margin === marginStyleString) {
log("_roundContentView[" + logId + "] is_rounded == true");
if (this._isLetterboxingTesting) {
log(
@@ -563,19 +605,35 @@ class _RFPHelper {
"_roundContentView[" +
logId +
"] setting margins to " +
- margins.width +
- " x " +
- margins.height
+ marginStyleString
);
- // One cannot (easily) control the color of a margin unfortunately.
- // An initial attempt to use a border instead of a margin resulted
- // in offset event dispatching; so for now we use a colorless margin.
- aBrowser.style.margin = `${margins.height}px ${margins.width}px`;
+
+ // The margin background color is determined by the background color of the
+ // window's tabpanels#tabbrowser-tabpanels element
+ aBrowser.style.margin = marginStyleString;
});
}
_clearContentViewMargin(aBrowser) {
+ const borderDimensions = this.getBorderDimensions(aBrowser);
+ // set the margins such that the browser elements border is visible up top, but
+ // are rendered off-screen on the remaining sides
+ let margins = {
+ top : 0,
+ right : -borderDimensions.right,
+ bottom : -borderDimensions.bottom,
+ left : -borderDimensions.left,
+ };
+ const marginStyleString = `${margins.top}px ${margins.right}px ${margins.bottom}px ${margins.left}px`;
+
+ aBrowser.ownerGlobal.requestAnimationFrame(() => {
+ aBrowser.style.margin = marginStyleString;
+ });
+ }
+
+ _removeLetterboxing(aBrowser) {
aBrowser.ownerGlobal.requestAnimationFrame(() => {
+ aBrowser.classList.remove("letterboxing");
aBrowser.style.margin = "";
});
}
@@ -593,6 +651,11 @@ class _RFPHelper {
aWindow.gBrowser.addTabsProgressListener(this);
aWindow.addEventListener("TabOpen", this);
+ const tabPanel = aWindow.document.getElementById("tabbrowser-tabpanels");
+ if (tabPanel) {
+ tabPanel.classList.add("letterboxing");
+ }
+
// Rounding the content viewport.
this._updateMarginsForTabsInWindow(aWindow);
}
@@ -616,10 +679,17 @@ class _RFPHelper {
tabBrowser.removeTabsProgressListener(this);
aWindow.removeEventListener("TabOpen", this);
- // Clear all margins and tooltip for all browsers.
+ // revert tabpanel's background colors to default
+ const tabPanel = aWindow.document.getElementById("tabbrowser-tabpanels");
+ if (tabPanel) {
+ tabPanel.classList.remove("letterboxing");
+ }
+
+ // and revert each browser element to default,
+ // restore default margins and remove letterboxing class
for (let tab of tabBrowser.tabs) {
let browser = tab.linkedBrowser;
- this._clearContentViewMargin(browser);
+ this._removeLetterboxing(browser);
}
}
1
0

[tor-browser/tor-browser-78.9.0esr-10.5-1] Bug 32658: Create a new MAR signing key
by sysrqb@torproject.org 17 Mar '21
by sysrqb@torproject.org 17 Mar '21
17 Mar '21
commit ae890c09ace4a118029edb69ed1770ba573d1d59
Author: Georg Koppen <gk(a)torproject.org>
Date: Fri Jan 17 12:54:31 2020 +0000
Bug 32658: Create a new MAR signing key
It's time for our rotation again: Move the backup key in the front
position and add a new backup key.
squash! Bug 32658: Create a new MAR signing key
Bug 33803: Move our primary nightly MAR signing key to tor-browser
Bug 33803: Add a secondary nightly MAR signing key
---
.../update/updater/nightly_aurora_level3_primary.der | Bin 1225 -> 1245 bytes
.../updater/nightly_aurora_level3_secondary.der | Bin 1225 -> 1245 bytes
toolkit/mozapps/update/updater/release_primary.der | Bin 1225 -> 1229 bytes
toolkit/mozapps/update/updater/release_secondary.der | Bin 1225 -> 1229 bytes
4 files changed, 0 insertions(+), 0 deletions(-)
diff --git a/toolkit/mozapps/update/updater/nightly_aurora_level3_primary.der b/toolkit/mozapps/update/updater/nightly_aurora_level3_primary.der
index 44fd95dcff89..d579cf801e1a 100644
Binary files a/toolkit/mozapps/update/updater/nightly_aurora_level3_primary.der and b/toolkit/mozapps/update/updater/nightly_aurora_level3_primary.der differ
diff --git a/toolkit/mozapps/update/updater/nightly_aurora_level3_secondary.der b/toolkit/mozapps/update/updater/nightly_aurora_level3_secondary.der
index 90f8e6e82c63..7cbfa77d06e7 100644
Binary files a/toolkit/mozapps/update/updater/nightly_aurora_level3_secondary.der and b/toolkit/mozapps/update/updater/nightly_aurora_level3_secondary.der differ
diff --git a/toolkit/mozapps/update/updater/release_primary.der b/toolkit/mozapps/update/updater/release_primary.der
index 1d94f88ad73b..0103a171de88 100644
Binary files a/toolkit/mozapps/update/updater/release_primary.der and b/toolkit/mozapps/update/updater/release_primary.der differ
diff --git a/toolkit/mozapps/update/updater/release_secondary.der b/toolkit/mozapps/update/updater/release_secondary.der
index 474706c4b73c..fcee3944e9b7 100644
Binary files a/toolkit/mozapps/update/updater/release_secondary.der and b/toolkit/mozapps/update/updater/release_secondary.der differ
1
0

[tor-browser/tor-browser-78.9.0esr-10.5-1] Bug 24796 - Comment out excess permissions from GeckoView
by sysrqb@torproject.org 17 Mar '21
by sysrqb@torproject.org 17 Mar '21
17 Mar '21
commit f251be31d82f79306ae77079cb055094c9ef2f3b
Author: Matthew Finkel <Matthew.Finkel(a)gmail.com>
Date: Wed Apr 11 17:52:59 2018 +0000
Bug 24796 - Comment out excess permissions from GeckoView
The GeckoView AndroidManifest.xml is not preprocessed unlike Fennec's
manifest, so we can't use the ifdef preprocessor guards around the
permissions we do not want. Commenting the permissions is the
next-best-thing.
---
.../android/geckoview/src/main/AndroidManifest.xml | 20 +++++++++++++++++---
1 file changed, 17 insertions(+), 3 deletions(-)
diff --git a/mobile/android/geckoview/src/main/AndroidManifest.xml b/mobile/android/geckoview/src/main/AndroidManifest.xml
index 87ad6dc28047..4c8ab2a9d996 100644
--- a/mobile/android/geckoview/src/main/AndroidManifest.xml
+++ b/mobile/android/geckoview/src/main/AndroidManifest.xml
@@ -6,20 +6,32 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="org.mozilla.geckoview">
+<!--#ifdef MOZ_ANDROID_NETWORK_STATE-->
+ <!--
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
+ -->
+<!--#endif-->
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.WAKE_LOCK"/>
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
+<!--#ifdef MOZ_ANDROID_LOCATION-->
+ <!--
<uses-feature
android:name="android.hardware.location"
android:required="false"/>
<uses-feature
android:name="android.hardware.location.gps"
android:required="false"/>
+ -->
+<!--#endif-->
<uses-feature
android:name="android.hardware.touchscreen"
android:required="false"/>
+<!--#ifdef MOZ_WEBRTC-->
+ <!-- TODO preprocess AndroidManifest.xml so that we can
+ conditionally include WebRTC permissions based on MOZ_WEBRTC. -->
+ <!--
<uses-feature
android:name="android.hardware.camera"
android:required="false"/>
@@ -28,14 +40,16 @@
android:required="false"/>
<uses-feature
- android:name="android.hardware.audio.low_latency"
+ android:name="android.hardware.camera.any"
android:required="false"/>
<uses-feature
- android:name="android.hardware.microphone"
+ android:name="android.hardware.audio.low_latency"
android:required="false"/>
<uses-feature
- android:name="android.hardware.camera.any"
+ android:name="android.hardware.microphone"
android:required="false"/>
+ -->
+<!--#endif-->
<!-- GeckoView requires OpenGL ES 2.0 -->
<uses-feature
1
0

[tor-browser/tor-browser-78.9.0esr-10.5-1] Orfox: Centralized proxy applied to AbstractCommunicator and BaseResources.
by sysrqb@torproject.org 17 Mar '21
by sysrqb@torproject.org 17 Mar '21
17 Mar '21
commit 1e0da6071dca096d744813f4cfc2f83fc0ab007c
Author: Amogh Pradeep <amoghbl1(a)gmail.com>
Date: Fri Jun 12 02:07:45 2015 -0400
Orfox: Centralized proxy applied to AbstractCommunicator and BaseResources.
See Bug 1357997 for partial uplift.
Also:
Bug 28051 - Use our Orbot for proxying our connections
Bug 31144 - ESR68 Network Code Review
---
.../main/java/org/mozilla/gecko/GeckoAppShell.java | 68 +++++++++++-----------
.../java/org/mozilla/gecko/util/BitmapUtils.java | 7 ---
.../java/org/mozilla/gecko/util/ProxySelector.java | 25 +++++++-
3 files changed, 59 insertions(+), 41 deletions(-)
diff --git a/mobile/android/geckoview/src/main/java/org/mozilla/gecko/GeckoAppShell.java b/mobile/android/geckoview/src/main/java/org/mozilla/gecko/GeckoAppShell.java
index 995b23316c32..b9ca73bee2eb 100644
--- a/mobile/android/geckoview/src/main/java/org/mozilla/gecko/GeckoAppShell.java
+++ b/mobile/android/geckoview/src/main/java/org/mozilla/gecko/GeckoAppShell.java
@@ -1764,39 +1764,41 @@ public class GeckoAppShell {
@WrapForJNI
private static URLConnection getConnection(final String url) {
- try {
- String spec;
- if (url.startsWith("android://")) {
- spec = url.substring(10);
- } else {
- spec = url.substring(8);
- }
-
- // Check if we are loading a package icon.
- try {
- if (spec.startsWith("icon/")) {
- String[] splits = spec.split("/");
- if (splits.length != 2) {
- return null;
- }
- final String pkg = splits[1];
- final PackageManager pm = getApplicationContext().getPackageManager();
- final Drawable d = pm.getApplicationIcon(pkg);
- final Bitmap bitmap = BitmapUtils.getBitmapFromDrawable(d);
- return new BitmapConnection(bitmap);
- }
- } catch (Exception ex) {
- Log.e(LOGTAG, "error", ex);
- }
-
- // if the colon got stripped, put it back
- int colon = spec.indexOf(':');
- if (colon == -1 || colon > spec.indexOf('/')) {
- spec = spec.replaceFirst("/", ":/");
- }
- } catch (Exception ex) {
- return null;
- }
+ // Bug 31144 - Prevent potential proxy-bypass
+
+ //try {
+ // String spec;
+ // if (url.startsWith("android://")) {
+ // spec = url.substring(10);
+ // } else {
+ // spec = url.substring(8);
+ // }
+
+ // // Check if we are loading a package icon.
+ // try {
+ // if (spec.startsWith("icon/")) {
+ // String[] splits = spec.split("/");
+ // if (splits.length != 2) {
+ // return null;
+ // }
+ // final String pkg = splits[1];
+ // final PackageManager pm = getApplicationContext().getPackageManager();
+ // final Drawable d = pm.getApplicationIcon(pkg);
+ // final Bitmap bitmap = BitmapUtils.getBitmapFromDrawable(d);
+ // return new BitmapConnection(bitmap);
+ // }
+ // } catch (Exception ex) {
+ // Log.e(LOGTAG, "error", ex);
+ // }
+
+ // // if the colon got stripped, put it back
+ // int colon = spec.indexOf(':');
+ // if (colon == -1 || colon > spec.indexOf('/')) {
+ // spec = spec.replaceFirst("/", ":/");
+ // }
+ //} catch (Exception ex) {
+ // return null;
+ //}
return null;
}
diff --git a/mobile/android/geckoview/src/main/java/org/mozilla/gecko/util/BitmapUtils.java b/mobile/android/geckoview/src/main/java/org/mozilla/gecko/util/BitmapUtils.java
index 73a69a3abd66..f795dacffb47 100644
--- a/mobile/android/geckoview/src/main/java/org/mozilla/gecko/util/BitmapUtils.java
+++ b/mobile/android/geckoview/src/main/java/org/mozilla/gecko/util/BitmapUtils.java
@@ -101,13 +101,6 @@ public final class BitmapUtils {
public static Bitmap decodeUrl(final URL url) {
InputStream stream = null;
- try {
- stream = url.openStream();
- } catch (IOException e) {
- Log.w(LOGTAG, "decodeUrl: IOException downloading " + url);
- return null;
- }
-
if (stream == null) {
Log.w(LOGTAG, "decodeUrl: stream not found downloading " + url);
return null;
diff --git a/mobile/android/geckoview/src/main/java/org/mozilla/gecko/util/ProxySelector.java b/mobile/android/geckoview/src/main/java/org/mozilla/gecko/util/ProxySelector.java
index 3940d3c84249..9515975f680a 100644
--- a/mobile/android/geckoview/src/main/java/org/mozilla/gecko/util/ProxySelector.java
+++ b/mobile/android/geckoview/src/main/java/org/mozilla/gecko/util/ProxySelector.java
@@ -29,6 +29,10 @@ import java.net.URLConnection;
import java.util.List;
public class ProxySelector {
+ private static final String TOR_PROXY_ADDRESS = "127.0.0.1";
+ private static final int TOR_SOCKS_PROXY_PORT = 9150;
+ private static final int TOR_HTTP_PROXY_PORT = 8218;
+
public static URLConnection openConnectionWithProxy(final URI uri) throws IOException {
java.net.ProxySelector ps = java.net.ProxySelector.getDefault();
Proxy proxy = Proxy.NO_PROXY;
@@ -39,7 +43,26 @@ public class ProxySelector {
}
}
- return uri.toURL().openConnection(proxy);
+ /* Ignore the proxy we found from the VM, only use Tor. We can probably
+ * safely use the logic in this class in the future. */
+ return uri.toURL().openConnection(getProxy());
+ }
+
+ public static Proxy getProxy() {
+ // TODO make configurable
+ return new Proxy(Proxy.Type.SOCKS, new InetSocketAddress(TOR_PROXY_ADDRESS, TOR_SOCKS_PROXY_PORT));
+ }
+
+ public static String getProxyHostAddress() {
+ return TOR_PROXY_ADDRESS;
+ }
+
+ public static int getSocksProxyPort() {
+ return TOR_SOCKS_PROXY_PORT;
+ }
+
+ public static int getHttpProxyPort() {
+ return TOR_HTTP_PROXY_PORT;
}
public ProxySelector() {
1
0

[tor-browser/tor-browser-78.9.0esr-10.5-1] Bug 30237: Add v3 onion services client authentication prompt
by sysrqb@torproject.org 17 Mar '21
by sysrqb@torproject.org 17 Mar '21
17 Mar '21
commit 33d7b1ec40cfd9456b16a6a695b76db93f257023
Author: Kathy Brade <brade(a)pearlcrescent.com>
Date: Tue Nov 12 16:11:05 2019 -0500
Bug 30237: Add v3 onion services client authentication prompt
When Tor informs the browser that client authentication is needed,
temporarily load about:blank instead of about:neterror and prompt
for the user's key.
If a correctly formatted key is entered, use Tor's ONION_CLIENT_AUTH_ADD
control port command to add the key (via Torbutton's control port
module) and reload the page.
If the user cancels the prompt, display the standard about:neterror
"Unable to connect" page. This requires a small change to
browser/actors/NetErrorChild.jsm to account for the fact that the
docShell no longer has the failedChannel information. The failedChannel
is used to extract TLS-related error info, which is not applicable
in the case of a canceled .onion authentication prompt.
Add a leaveOpen option to PopupNotifications.show so we can display
error messages within the popup notification doorhanger without
closing the prompt.
Add support for onion services strings to the TorStrings module.
Add support for Tor extended SOCKS errors (Tor proposal 304) to the
socket transport and SOCKS layers. Improved display of all of these
errors will be implemented as part of bug 30025.
Also fixes bug 19757:
Add a "Remember this key" checkbox to the client auth prompt.
Add an "Onion Services Authentication" section within the
about:preferences "Privacy & Security section" to allow
viewing and removal of v3 onion client auth keys that have
been stored on disk.
Also fixes bug 19251: use enhanced error pages for onion service errors.
---
browser/actors/NetErrorChild.jsm | 7 +
browser/base/content/aboutNetError.js | 10 +-
browser/base/content/aboutNetError.xhtml | 1 +
browser/base/content/browser.js | 10 +
browser/base/content/browser.xhtml | 3 +
browser/base/content/tab-content.js | 5 +
browser/components/moz.build | 1 +
.../content/authNotificationIcon.inc.xhtml | 6 +
.../onionservices/content/authPopup.inc.xhtml | 16 ++
.../onionservices/content/authPreferences.css | 20 ++
.../content/authPreferences.inc.xhtml | 19 ++
.../onionservices/content/authPreferences.js | 66 +++++
.../components/onionservices/content/authPrompt.js | 316 +++++++++++++++++++++
.../components/onionservices/content/authUtil.jsm | 47 +++
.../onionservices/content/netError/browser.svg | 3 +
.../onionservices/content/netError/network.svg | 3 +
.../content/netError/onionNetError.css | 65 +++++
.../content/netError/onionNetError.js | 244 ++++++++++++++++
.../onionservices/content/netError/onionsite.svg | 7 +
.../onionservices/content/onionservices.css | 69 +++++
.../onionservices/content/savedKeysDialog.js | 259 +++++++++++++++++
.../onionservices/content/savedKeysDialog.xhtml | 42 +++
browser/components/onionservices/jar.mn | 9 +
browser/components/onionservices/moz.build | 1 +
browser/components/preferences/preferences.xhtml | 1 +
browser/components/preferences/privacy.inc.xhtml | 2 +
browser/components/preferences/privacy.js | 7 +
browser/themes/shared/notification-icons.inc.css | 3 +
docshell/base/nsDocShell.cpp | 81 +++++-
dom/ipc/BrowserParent.cpp | 21 ++
dom/ipc/BrowserParent.h | 3 +
dom/ipc/PBrowser.ipdl | 9 +
js/xpconnect/src/xpc.msg | 10 +
netwerk/base/nsSocketTransport2.cpp | 6 +
netwerk/socket/nsSOCKSIOLayer.cpp | 49 ++++
toolkit/modules/PopupNotifications.jsm | 6 +
toolkit/modules/RemotePageAccessManager.jsm | 1 +
.../lib/environments/frame-script.js | 1 +
xpcom/base/ErrorList.py | 22 ++
39 files changed, 1449 insertions(+), 2 deletions(-)
diff --git a/browser/actors/NetErrorChild.jsm b/browser/actors/NetErrorChild.jsm
index af9d6bd46128..de66e9eeda18 100644
--- a/browser/actors/NetErrorChild.jsm
+++ b/browser/actors/NetErrorChild.jsm
@@ -13,6 +13,8 @@ const { RemotePageChild } = ChromeUtils.import(
"resource://gre/actors/RemotePageChild.jsm"
);
+const { TorStrings } = ChromeUtils.import("resource:///modules/TorStrings.jsm");
+
XPCOMUtils.defineLazyServiceGetter(
this,
"gSerializationHelper",
@@ -29,6 +31,7 @@ class NetErrorChild extends RemotePageChild {
"RPMPrefIsLocked",
"RPMAddToHistogram",
"RPMRecordTelemetryEvent",
+ "RPMGetTorStrings",
];
this.exportFunctions(exportableFunctions);
}
@@ -82,4 +85,8 @@ class NetErrorChild extends RemotePageChild {
RPMRecordTelemetryEvent(category, event, object, value, extra) {
Services.telemetry.recordEvent(category, event, object, value, extra);
}
+
+ RPMGetTorStrings() {
+ return Cu.cloneInto(TorStrings.onionServices, this.contentWindow);
+ }
}
diff --git a/browser/base/content/aboutNetError.js b/browser/base/content/aboutNetError.js
index 053d26ade512..60db17f46eb9 100644
--- a/browser/base/content/aboutNetError.js
+++ b/browser/base/content/aboutNetError.js
@@ -3,6 +3,7 @@
* You can obtain one at http://mozilla.org/MPL/2.0/. */
/* eslint-env mozilla/frame-script */
+/* import-globals-from ../../components/onionservices/content/netError/onionNetError.js */
const formatter = new Intl.DateTimeFormat("default");
@@ -241,7 +242,10 @@ function initPage() {
errDesc = document.getElementById("ed_generic");
}
- setErrorPageStrings(err);
+ const isOnionError = err.startsWith("onionServices.");
+ if (!isOnionError) {
+ setErrorPageStrings(err);
+ }
var sd = document.getElementById("errorShortDescText");
if (sd) {
@@ -387,6 +391,10 @@ function initPage() {
span.textContent = document.location.hostname;
}
}
+
+ if (isOnionError) {
+ OnionServicesAboutNetError.initPage(document);
+ }
}
function setupErrorUI() {
diff --git a/browser/base/content/aboutNetError.xhtml b/browser/base/content/aboutNetError.xhtml
index 3e9677e3c0ff..957b6f15a0be 100644
--- a/browser/base/content/aboutNetError.xhtml
+++ b/browser/base/content/aboutNetError.xhtml
@@ -208,5 +208,6 @@
</div>
</div>
</body>
+ <script src="chrome://browser/content/onionservices/netError/onionNetError.js"/>
<script src="chrome://browser/content/aboutNetError.js"/>
</html>
diff --git a/browser/base/content/browser.js b/browser/base/content/browser.js
index a851be586c0c..9f5f0c608536 100644
--- a/browser/base/content/browser.js
+++ b/browser/base/content/browser.js
@@ -221,6 +221,11 @@ XPCOMUtils.defineLazyScriptGetter(
["SecurityLevelButton"],
"chrome://browser/content/securitylevel/securityLevel.js"
);
+XPCOMUtils.defineLazyScriptGetter(
+ this,
+ ["OnionAuthPrompt"],
+ "chrome://browser/content/onionservices/authPrompt.js"
+);
XPCOMUtils.defineLazyScriptGetter(
this,
"gEditItemOverlay",
@@ -1884,6 +1889,9 @@ var gBrowserInit = {
// Init the SecuritySettingsButton
SecurityLevelButton.init();
+ // Init the OnionAuthPrompt
+ OnionAuthPrompt.init();
+
// Certain kinds of automigration rely on this notification to complete
// their tasks BEFORE the browser window is shown. SessionStore uses it to
// restore tabs into windows AFTER important parts like gMultiProcessBrowser
@@ -2568,6 +2576,8 @@ var gBrowserInit = {
SecurityLevelButton.uninit();
+ OnionAuthPrompt.uninit();
+
gAccessibilityServiceIndicator.uninit();
AccessibilityRefreshBlocker.uninit();
diff --git a/browser/base/content/browser.xhtml b/browser/base/content/browser.xhtml
index ddf5d766126b..4cab5fad6475 100644
--- a/browser/base/content/browser.xhtml
+++ b/browser/base/content/browser.xhtml
@@ -33,6 +33,7 @@
<?xml-stylesheet href="chrome://browser/skin/places/editBookmark.css" type="text/css"?>
<?xml-stylesheet href="chrome://torbutton/skin/tor-circuit-display.css" type="text/css"?>
<?xml-stylesheet href="chrome://torbutton/skin/torbutton.css" type="text/css"?>
+<?xml-stylesheet href="chrome://browser/content/onionservices/onionservices.css" type="text/css"?>
# All DTD information is stored in a separate file so that it can be shared by
# hiddenWindowMac.xhtml.
@@ -626,6 +627,7 @@
#include ../../components/downloads/content/downloadsPanel.inc.xhtml
#include ../../../devtools/startup/enableDevToolsPopup.inc.xhtml
#include ../../components/securitylevel/content/securityLevelPanel.inc.xhtml
+#include ../../components/onionservices/content/authPopup.inc.xhtml
#include browser-allTabsMenu.inc.xhtml
<hbox id="downloads-animation-container">
@@ -994,6 +996,7 @@
data-l10n-id="urlbar-indexed-db-notification-anchor"/>
<image id="password-notification-icon" class="notification-anchor-icon login-icon" role="button"
data-l10n-id="urlbar-password-notification-anchor"/>
+#include ../../components/onionservices/content/authNotificationIcon.inc.xhtml
<stack id="plugins-notification-icon" class="notification-anchor-icon" role="button" align="center" data-l10n-id="urlbar-plugins-notification-anchor">
<image class="plugin-icon" />
<image id="plugin-icon-badge" />
diff --git a/browser/base/content/tab-content.js b/browser/base/content/tab-content.js
index 30cfa891c1fb..c57244a962ee 100644
--- a/browser/base/content/tab-content.js
+++ b/browser/base/content/tab-content.js
@@ -19,6 +19,9 @@ ChromeUtils.defineModuleGetter(
"BrowserUtils",
"resource://gre/modules/BrowserUtils.jsm"
);
+var { OnionAuthUtil } = ChromeUtils.import(
+ "chrome://browser/content/onionservices/authUtil.jsm"
+);
var { ActorManagerChild } = ChromeUtils.import(
"resource://gre/modules/ActorManagerChild.jsm"
@@ -101,5 +104,7 @@ if (Services.appinfo.processType == Services.appinfo.PROCESS_TYPE_CONTENT) {
Services.obs.notifyObservers(this, "tab-content-frameloader-created");
+OnionAuthUtil.addCancelMessageListener(this, docShell);
+
// This is a temporary hack to prevent regressions (bug 1471327).
void content;
diff --git a/browser/components/moz.build b/browser/components/moz.build
index 09e209dc9c3b..b660be047b14 100644
--- a/browser/components/moz.build
+++ b/browser/components/moz.build
@@ -41,6 +41,7 @@ DIRS += [
'fxmonitor',
'migration',
'newtab',
+ 'onionservices',
'originattributes',
'pioneer',
'places',
diff --git a/browser/components/onionservices/content/authNotificationIcon.inc.xhtml b/browser/components/onionservices/content/authNotificationIcon.inc.xhtml
new file mode 100644
index 000000000000..91274d612739
--- /dev/null
+++ b/browser/components/onionservices/content/authNotificationIcon.inc.xhtml
@@ -0,0 +1,6 @@
+# Copyright (c) 2020, The Tor Project, Inc.
+
+<image id="tor-clientauth-notification-icon"
+ class="notification-anchor-icon tor-clientauth-icon"
+ role="button"
+ tooltiptext="&torbutton.onionServices.authPrompt.tooltip;"/>
diff --git a/browser/components/onionservices/content/authPopup.inc.xhtml b/browser/components/onionservices/content/authPopup.inc.xhtml
new file mode 100644
index 000000000000..bd0ec3aa0b00
--- /dev/null
+++ b/browser/components/onionservices/content/authPopup.inc.xhtml
@@ -0,0 +1,16 @@
+# Copyright (c) 2020, The Tor Project, Inc.
+
+<popupnotification id="tor-clientauth-notification" hidden="true">
+ <popupnotificationcontent orient="vertical">
+ <description id="tor-clientauth-notification-desc"/>
+ <label id="tor-clientauth-notification-learnmore"
+ class="text-link popup-notification-learnmore-link"
+ is="text-link"/>
+ <html:div>
+ <html:input id="tor-clientauth-notification-key" type="password"/>
+ <html:div id="tor-clientauth-warning"/>
+ <checkbox id="tor-clientauth-persistkey-checkbox"
+ label="&torbutton.onionServices.authPrompt.persistCheckboxLabel;"/>
+ </html:div>
+ </popupnotificationcontent>
+</popupnotification>
diff --git a/browser/components/onionservices/content/authPreferences.css b/browser/components/onionservices/content/authPreferences.css
new file mode 100644
index 000000000000..b3fb79b26ddc
--- /dev/null
+++ b/browser/components/onionservices/content/authPreferences.css
@@ -0,0 +1,20 @@
+/* Copyright (c) 2020, The Tor Project, Inc. */
+
+#torOnionServiceKeys-overview-container {
+ margin-right: 30px;
+}
+
+#onionservices-savedkeys-tree treechildren::-moz-tree-cell-text {
+ font-size: 80%;
+}
+
+#onionservices-savedkeys-errorContainer {
+ margin-top: 4px;
+ min-height: 3em;
+}
+
+#onionservices-savedkeys-errorIcon {
+ margin-right: 4px;
+ list-style-image: url("chrome://browser/skin/warning.svg");
+ visibility: hidden;
+}
diff --git a/browser/components/onionservices/content/authPreferences.inc.xhtml b/browser/components/onionservices/content/authPreferences.inc.xhtml
new file mode 100644
index 000000000000..f69c9dde66a2
--- /dev/null
+++ b/browser/components/onionservices/content/authPreferences.inc.xhtml
@@ -0,0 +1,19 @@
+# Copyright (c) 2020, The Tor Project, Inc.
+
+<groupbox id="torOnionServiceKeys" orient="vertical"
+ data-category="panePrivacy" hidden="true">
+ <label><html:h2 id="torOnionServiceKeys-header"/></label>
+ <hbox>
+ <description id="torOnionServiceKeys-overview-container" flex="1">
+ <html:span id="torOnionServiceKeys-overview"
+ class="tail-with-learn-more"/>
+ <label id="torOnionServiceKeys-learnMore" class="learnMore text-link"
+ is="text-link"/>
+ </description>
+ <vbox align="end">
+ <button id="torOnionServiceKeys-savedKeys"
+ is="highlightable-button"
+ class="accessory-button"/>
+ </vbox>
+ </hbox>
+</groupbox>
diff --git a/browser/components/onionservices/content/authPreferences.js b/browser/components/onionservices/content/authPreferences.js
new file mode 100644
index 000000000000..52f8272020cc
--- /dev/null
+++ b/browser/components/onionservices/content/authPreferences.js
@@ -0,0 +1,66 @@
+// Copyright (c) 2020, The Tor Project, Inc.
+
+"use strict";
+
+ChromeUtils.defineModuleGetter(
+ this,
+ "TorStrings",
+ "resource:///modules/TorStrings.jsm"
+);
+
+/*
+ Onion Services Client Authentication Preferences Code
+
+ Code to handle init and update of onion services authentication section
+ in about:preferences#privacy
+*/
+
+const OnionServicesAuthPreferences = {
+ selector: {
+ groupBox: "#torOnionServiceKeys",
+ header: "#torOnionServiceKeys-header",
+ overview: "#torOnionServiceKeys-overview",
+ learnMore: "#torOnionServiceKeys-learnMore",
+ savedKeysButton: "#torOnionServiceKeys-savedKeys",
+ },
+
+ init() {
+ // populate XUL with localized strings
+ this._populateXUL();
+ },
+
+ _populateXUL() {
+ const groupbox = document.querySelector(this.selector.groupBox);
+
+ let elem = groupbox.querySelector(this.selector.header);
+ elem.textContent = TorStrings.onionServices.authPreferences.header;
+
+ elem = groupbox.querySelector(this.selector.overview);
+ elem.textContent = TorStrings.onionServices.authPreferences.overview;
+
+ elem = groupbox.querySelector(this.selector.learnMore);
+ elem.setAttribute("value", TorStrings.onionServices.learnMore);
+ elem.setAttribute("href", TorStrings.onionServices.learnMoreURL);
+
+ elem = groupbox.querySelector(this.selector.savedKeysButton);
+ elem.setAttribute(
+ "label",
+ TorStrings.onionServices.authPreferences.savedKeys
+ );
+ elem.addEventListener("command", () =>
+ OnionServicesAuthPreferences.onViewSavedKeys()
+ );
+ },
+
+ onViewSavedKeys() {
+ gSubDialog.open(
+ "chrome://browser/content/onionservices/savedKeysDialog.xhtml"
+ );
+ },
+}; // OnionServicesAuthPreferences
+
+Object.defineProperty(this, "OnionServicesAuthPreferences", {
+ value: OnionServicesAuthPreferences,
+ enumerable: true,
+ writable: false,
+});
diff --git a/browser/components/onionservices/content/authPrompt.js b/browser/components/onionservices/content/authPrompt.js
new file mode 100644
index 000000000000..d4a59ac46487
--- /dev/null
+++ b/browser/components/onionservices/content/authPrompt.js
@@ -0,0 +1,316 @@
+// Copyright (c) 2020, The Tor Project, Inc.
+
+"use strict";
+
+XPCOMUtils.defineLazyModuleGetters(this, {
+ OnionAuthUtil: "chrome://browser/content/onionservices/authUtil.jsm",
+ CommonUtils: "resource://services-common/utils.js",
+ TorStrings: "resource:///modules/TorStrings.jsm",
+});
+
+const OnionAuthPrompt = (function() {
+ // OnionServicesAuthPrompt objects run within the main/chrome process.
+ // aReason is the topic passed within the observer notification that is
+ // causing this auth prompt to be displayed.
+ function OnionServicesAuthPrompt(aBrowser, aFailedURI, aReason, aOnionName) {
+ this._browser = aBrowser;
+ this._failedURI = aFailedURI;
+ this._reasonForPrompt = aReason;
+ this._onionName = aOnionName;
+ }
+
+ OnionServicesAuthPrompt.prototype = {
+ show(aWarningMessage) {
+ let mainAction = {
+ label: TorStrings.onionServices.authPrompt.done,
+ accessKey: TorStrings.onionServices.authPrompt.doneAccessKey,
+ leaveOpen: true, // Callback is responsible for closing the notification.
+ callback: this._onDone.bind(this),
+ };
+
+ let dialogBundle = Services.strings.createBundle(
+ "chrome://global/locale/dialog.properties");
+
+ let cancelAccessKey = dialogBundle.GetStringFromName("accesskey-cancel");
+ if (!cancelAccessKey)
+ cancelAccessKey = "c"; // required by PopupNotifications.show()
+
+ let cancelAction = {
+ label: dialogBundle.GetStringFromName("button-cancel"),
+ accessKey: cancelAccessKey,
+ callback: this._onCancel.bind(this),
+ };
+
+ let _this = this;
+ let options = {
+ autofocus: true,
+ hideClose: true,
+ persistent: true,
+ removeOnDismissal: false,
+ eventCallback(aTopic) {
+ if (aTopic === "showing") {
+ _this._onPromptShowing(aWarningMessage);
+ } else if (aTopic === "shown") {
+ _this._onPromptShown();
+ } else if (aTopic === "removed") {
+ _this._onPromptRemoved();
+ }
+ }
+ };
+
+ this._prompt = PopupNotifications.show(this._browser,
+ OnionAuthUtil.domid.notification, "",
+ OnionAuthUtil.domid.anchor,
+ mainAction, [cancelAction], options);
+ },
+
+ _onPromptShowing(aWarningMessage) {
+ let xulDoc = this._browser.ownerDocument;
+ let descElem = xulDoc.getElementById(OnionAuthUtil.domid.description);
+ if (descElem) {
+ // Handle replacement of the onion name within the localized
+ // string ourselves so we can show the onion name as bold text.
+ // We do this by splitting the localized string and creating
+ // several HTML <span> elements.
+ while (descElem.firstChild)
+ descElem.removeChild(descElem.firstChild);
+
+ let fmtString = TorStrings.onionServices.authPrompt.description;
+ let prefix = "";
+ let suffix = "";
+ const kToReplace = "%S";
+ let idx = fmtString.indexOf(kToReplace);
+ if (idx < 0) {
+ prefix = fmtString;
+ } else {
+ prefix = fmtString.substring(0, idx);
+ suffix = fmtString.substring(idx + kToReplace.length);
+ }
+
+ const kHTMLNS = "http://www.w3.org/1999/xhtml";
+ let span = xulDoc.createElementNS(kHTMLNS, "span");
+ span.textContent = prefix;
+ descElem.appendChild(span);
+ span = xulDoc.createElementNS(kHTMLNS, "span");
+ span.id = OnionAuthUtil.domid.onionNameSpan;
+ span.textContent = this._onionName;
+ descElem.appendChild(span);
+ span = xulDoc.createElementNS(kHTMLNS, "span");
+ span.textContent = suffix;
+ descElem.appendChild(span);
+ }
+
+ // Set "Learn More" label and href.
+ let learnMoreElem = xulDoc.getElementById(OnionAuthUtil.domid.learnMore);
+ if (learnMoreElem) {
+ learnMoreElem.setAttribute("value", TorStrings.onionServices.learnMore);
+ learnMoreElem.setAttribute("href", TorStrings.onionServices.learnMoreURL);
+ }
+
+ this._showWarning(aWarningMessage);
+ let checkboxElem = this._getCheckboxElement();
+ if (checkboxElem) {
+ checkboxElem.checked = false;
+ }
+ },
+
+ _onPromptShown() {
+ let keyElem = this._getKeyElement();
+ if (keyElem) {
+ keyElem.setAttribute("placeholder",
+ TorStrings.onionServices.authPrompt.keyPlaceholder);
+ this._boundOnKeyFieldKeyPress = this._onKeyFieldKeyPress.bind(this);
+ this._boundOnKeyFieldInput = this._onKeyFieldInput.bind(this);
+ keyElem.addEventListener("keypress", this._boundOnKeyFieldKeyPress);
+ keyElem.addEventListener("input", this._boundOnKeyFieldInput);
+ keyElem.focus();
+ }
+ },
+
+ _onPromptRemoved() {
+ if (this._boundOnKeyFieldKeyPress) {
+ let keyElem = this._getKeyElement();
+ if (keyElem) {
+ keyElem.value = "";
+ keyElem.removeEventListener("keypress",
+ this._boundOnKeyFieldKeyPress);
+ this._boundOnKeyFieldKeyPress = undefined;
+ keyElem.removeEventListener("input", this._boundOnKeyFieldInput);
+ this._boundOnKeyFieldInput = undefined;
+ }
+ }
+ },
+
+ _onKeyFieldKeyPress(aEvent) {
+ if (aEvent.keyCode == aEvent.DOM_VK_RETURN) {
+ this._onDone();
+ } else if (aEvent.keyCode == aEvent.DOM_VK_ESCAPE) {
+ this._prompt.remove();
+ this._onCancel();
+ }
+ },
+
+ _onKeyFieldInput(aEvent) {
+ this._showWarning(undefined); // Remove the warning.
+ },
+
+ _onDone() {
+ let keyElem = this._getKeyElement();
+ if (!keyElem)
+ return;
+
+ let base64key = this._keyToBase64(keyElem.value);
+ if (!base64key) {
+ this._showWarning(TorStrings.onionServices.authPrompt.invalidKey);
+ return;
+ }
+
+ this._prompt.remove();
+
+ // Use Torbutton's controller module to add the private key to Tor.
+ let controllerFailureMsg =
+ TorStrings.onionServices.authPrompt.failedToSetKey;
+ try {
+ let { controller } =
+ Cu.import("resource://torbutton/modules/tor-control-port.js", {});
+ let torController = controller(aError => {
+ this.show(controllerFailureMsg);
+ });
+ let onionAddr = this._onionName.toLowerCase().replace(/\.onion$/, "");
+ let checkboxElem = this._getCheckboxElement();
+ let isPermanent = (checkboxElem && checkboxElem.checked);
+ torController.onionAuthAdd(onionAddr, base64key, isPermanent)
+ .then(aResponse => {
+ // Success! Reload the page.
+ this._browser.sendMessageToActor(
+ "Browser:Reload",
+ {},
+ "BrowserTab"
+ );
+ })
+ .catch(aError => {
+ if (aError.torMessage)
+ this.show(aError.torMessage);
+ else
+ this.show(controllerFailureMsg);
+ });
+ } catch (e) {
+ this.show(controllerFailureMsg);
+ }
+ },
+
+ _onCancel() {
+ // Arrange for an error page to be displayed.
+ this._browser.messageManager.sendAsyncMessage(
+ OnionAuthUtil.message.authPromptCanceled,
+ {failedURI: this._failedURI.spec,
+ reasonForPrompt: this._reasonForPrompt});
+ },
+
+ _getKeyElement() {
+ let xulDoc = this._browser.ownerDocument;
+ return xulDoc.getElementById(OnionAuthUtil.domid.keyElement);
+ },
+
+ _getCheckboxElement() {
+ let xulDoc = this._browser.ownerDocument;
+ return xulDoc.getElementById(OnionAuthUtil.domid.checkboxElement);
+ },
+
+ _showWarning(aWarningMessage) {
+ let xulDoc = this._browser.ownerDocument;
+ let warningElem =
+ xulDoc.getElementById(OnionAuthUtil.domid.warningElement);
+ let keyElem = this._getKeyElement();
+ if (warningElem) {
+ if (aWarningMessage) {
+ warningElem.textContent = aWarningMessage;
+ warningElem.removeAttribute("hidden");
+ if (keyElem)
+ keyElem.className = "invalid";
+ } else {
+ warningElem.setAttribute("hidden", "true");
+ if (keyElem)
+ keyElem.className = "";
+ }
+ }
+ },
+
+ // Returns undefined if the key is the wrong length or format.
+ _keyToBase64(aKeyString) {
+ if (!aKeyString)
+ return undefined;
+
+ let base64key;
+ if (aKeyString.length == 52) {
+ // The key is probably base32-encoded. Attempt to decode.
+ // Although base32 specifies uppercase letters, we accept lowercase
+ // as well because users may type in lowercase or copy a key out of
+ // a tor onion-auth file (which uses lowercase).
+ let rawKey;
+ try {
+ rawKey = CommonUtils.decodeBase32(aKeyString.toUpperCase());
+ } catch (e) {}
+
+ if (rawKey) try {
+ base64key = btoa(rawKey);
+ } catch (e) {}
+ } else if ((aKeyString.length == 44) &&
+ /^[a-zA-Z0-9+/]*=*$/.test(aKeyString)) {
+ // The key appears to be a correctly formatted base64 value. If not,
+ // tor will return an error when we try to add the key via the
+ // control port.
+ base64key = aKeyString;
+ }
+
+ return base64key;
+ },
+ };
+
+ let retval = {
+ init() {
+ Services.obs.addObserver(this, OnionAuthUtil.topic.clientAuthMissing);
+ Services.obs.addObserver(this, OnionAuthUtil.topic.clientAuthIncorrect);
+ },
+
+ uninit() {
+ Services.obs.removeObserver(this, OnionAuthUtil.topic.clientAuthMissing);
+ Services.obs.removeObserver(this, OnionAuthUtil.topic.clientAuthIncorrect);
+ },
+
+ // aSubject is the DOM Window or browser where the prompt should be shown.
+ // aData contains the .onion name.
+ observe(aSubject, aTopic, aData) {
+ if ((aTopic != OnionAuthUtil.topic.clientAuthMissing) &&
+ (aTopic != OnionAuthUtil.topic.clientAuthIncorrect)) {
+ return;
+ }
+
+ let browser;
+ if (aSubject instanceof Ci.nsIDOMWindow) {
+ let contentWindow = aSubject.QueryInterface(Ci.nsIDOMWindow);
+ browser = contentWindow.docShell.chromeEventHandler;
+ } else {
+ browser = aSubject.QueryInterface(Ci.nsIBrowser);
+ }
+
+ if (!gBrowser.browsers.some(aBrowser => aBrowser == browser)) {
+ return; // This window does not contain the subject browser; ignore.
+ }
+
+ let failedURI = browser.currentURI;
+ let authPrompt = new OnionServicesAuthPrompt(browser, failedURI,
+ aTopic, aData);
+ authPrompt.show(undefined);
+ }
+ };
+
+ return retval;
+})(); /* OnionAuthPrompt */
+
+
+Object.defineProperty(this, "OnionAuthPrompt", {
+ value: OnionAuthPrompt,
+ enumerable: true,
+ writable: false
+});
diff --git a/browser/components/onionservices/content/authUtil.jsm b/browser/components/onionservices/content/authUtil.jsm
new file mode 100644
index 000000000000..c9d83774da1f
--- /dev/null
+++ b/browser/components/onionservices/content/authUtil.jsm
@@ -0,0 +1,47 @@
+// Copyright (c) 2020, The Tor Project, Inc.
+
+"use strict";
+
+var EXPORTED_SYMBOLS = [
+ "OnionAuthUtil",
+];
+
+var { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm");
+
+const OnionAuthUtil = {
+ topic: {
+ clientAuthMissing: "tor-onion-services-clientauth-missing",
+ clientAuthIncorrect: "tor-onion-services-clientauth-incorrect",
+ },
+ message: {
+ authPromptCanceled: "Tor:OnionServicesAuthPromptCanceled",
+ },
+ domid: {
+ anchor: "tor-clientauth-notification-icon",
+ notification: "tor-clientauth",
+ description: "tor-clientauth-notification-desc",
+ learnMore: "tor-clientauth-notification-learnmore",
+ onionNameSpan: "tor-clientauth-notification-onionname",
+ keyElement: "tor-clientauth-notification-key",
+ warningElement: "tor-clientauth-warning",
+ checkboxElement: "tor-clientauth-persistkey-checkbox",
+ },
+
+ addCancelMessageListener(aTabContent, aDocShell) {
+ aTabContent.addMessageListener(this.message.authPromptCanceled,
+ (aMessage) => {
+ // Upon cancellation of the client authentication prompt, display
+ // the appropriate error page. When calling the docShell
+ // displayLoadError() function, we pass undefined for the failed
+ // channel so that displayLoadError() can determine that it should
+ // not display the client authentication prompt a second time.
+ let failedURI = Services.io.newURI(aMessage.data.failedURI);
+ let reasonForPrompt = aMessage.data.reasonForPrompt;
+ let errorCode =
+ (reasonForPrompt === this.topic.clientAuthMissing) ?
+ Cr.NS_ERROR_TOR_ONION_SVC_MISSING_CLIENT_AUTH :
+ Cr.NS_ERROR_TOR_ONION_SVC_BAD_CLIENT_AUTH;
+ aDocShell.displayLoadError(errorCode, failedURI, undefined, undefined);
+ });
+ },
+};
diff --git a/browser/components/onionservices/content/netError/browser.svg b/browser/components/onionservices/content/netError/browser.svg
new file mode 100644
index 000000000000..b4c433b37bbb
--- /dev/null
+++ b/browser/components/onionservices/content/netError/browser.svg
@@ -0,0 +1,3 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="72" height="65" viewBox="0 0 72 65">
+ <path fill="context-fill" fill-opacity="context-fill-opacity" d="M0.0 0.0C0.0 0.0 0.0 65.0 0.0 65.0C0.0 65.0 72.0 65.0 72.0 65.0C72.0 65.0 72.0 0.0 72.0 0.0C72.0 0.0 52.9019692 0.0 52.9019692 0.0C52.9019692 0.0 0.0 0.0 0.0 0.0C0.0 0.0 0.0 0.0 0.0 0.0M65.0 58.0C65.0 58.0 6.0 58.0 6.0 58.0C6.0 58.0 6.0 25.0 6.0 25.0C6.0 25.0 65.0 25.0 65.0 25.0C65.0 25.0 65.0 58.0 65.0 58.0C65.0 58.0 65.0 58.0 65.0 58.0M6.0 10.0C6.0 10.0 10.0 10.0 10.0 10.0C10.0 10.0 10.0 14.0 10.0 14.0C10.0 14.0 6.0 14.0 6.0 14.0C6.0 14.0 6.0 10.0 6.0 10.0C6.0 10.0 6.0 10.0 6.0 10.0M14.0 10.0C14.0 10.0 18.0 10.0 18.0 10.0C18.0 10.0 18.0 14.0 18.0 14.0C18.0 14.0 14.0 14.0 14.0 14.0C14.0 14.0 14.0 10.0 14.0 10.0C14.0 10.0 14.0 10.0 14.0 10.0M22.0 10.0C22.0 10.0 26.0 10.0 26.0 10.0C26.0 10.0 26.0 14.0 26.0 14.0C26.0 14.0 22.0 14.0 22.0 14.0C22.0 14.0 22.0 10.0 22.0 10.0C22.0 10.0 22.0 10.0 22.0 10.0" />
+</svg>
diff --git a/browser/components/onionservices/content/netError/network.svg b/browser/components/onionservices/content/netError/network.svg
new file mode 100644
index 000000000000..808c53dedd09
--- /dev/null
+++ b/browser/components/onionservices/content/netError/network.svg
@@ -0,0 +1,3 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="72" height="54" viewBox="0 0 72 54">
+ <path fill="context-fill" fill-opacity="context-fill-opacity" d="M14.0487805 54.0C6.28990244 54.0 0.0 47.3306322 0.0 39.1034585C0.0 32.0105634 4.68716488 26.0867675 10.9481707 24.585103C10.6902 23.574652 10.5365854 22.5107596 10.5365854 21.4138156C10.5365854 14.7292347 15.6471278 9.3103384 21.9512195 9.3103384C24.8076351 9.3103384 27.4126741 10.4393194 29.4146341 12.2780088C32.1344254 5.0777841 38.77452 0.0 46.5365854 0.0C56.7201249 0.0 64.9756098 8.7536733 64.9756098 19.5517479C64.9756098 20.7691677 64.8471688 21.9453428 64.6463415 23.1013144C69.0576849 26.0679606 72.0 31.2693674 72.0 37.2413909C72.0 46.5256603 64.9510244 54.0 56.195122 54.0C56.195122 54.0 14.0487805 54.0 14.0487805 54.0C14.0487805 54.0 14.0487805 54.0 14.0487805 54.0" />
+</svg>
diff --git a/browser/components/onionservices/content/netError/onionNetError.css b/browser/components/onionservices/content/netError/onionNetError.css
new file mode 100644
index 000000000000..58117ab93223
--- /dev/null
+++ b/browser/components/onionservices/content/netError/onionNetError.css
@@ -0,0 +1,65 @@
+/* Copyright (c) 2020, The Tor Project, Inc. */
+
+:root {
+ --grey-70: #38383d;
+}
+
+#onionErrorDiagramContainer {
+ margin: 60px auto;
+ width: 460px; /* 3 columns @ 140px plus 2 column gaps @ 20px */
+ display: grid;
+ grid-row-gap: 15px;
+ grid-column-gap: 20px;
+ grid-template-columns: 1fr 1fr 1fr;
+}
+
+#onionErrorDiagramContainer > div {
+ margin: auto;
+ position: relative; /* needed to allow overlay of the ok or error icon */
+}
+
+.onionErrorImage {
+ width: 72px;
+ height: 72px;
+ background-position: center;
+ background-repeat: no-repeat;
+ -moz-context-properties: fill;
+ fill: var(--grey-70);
+}
+
+#onionErrorBrowserImage {
+ background-image: url("browser.svg");
+}
+
+#onionErrorNetworkImage {
+ background-image: url("network.svg");
+}
+
+#onionErrorOnionSiteImage {
+ background-image: url("onionsite.svg");
+}
+
+/* rules to support overlay of the ok or error icon */
+.onionErrorImage[status]::after {
+ content: " ";
+ position: absolute;
+ left: -18px;
+ top: 18px;
+ width: 36px;
+ height: 36px;
+ -moz-context-properties: fill;
+ fill: var(--in-content-page-background);
+ background-color: var(--grey-70);
+ background-repeat: no-repeat;
+ background-position: center;
+ border: 3px solid var(--in-content-page-background);
+ border-radius: 50%;
+}
+
+.onionErrorImage[status="ok"]::after {
+ background-image: url("chrome://global/skin/icons/check.svg");
+}
+
+.onionErrorImage[status="error"]::after {
+ background-image: url("chrome://browser/skin/stop.svg");
+}
diff --git a/browser/components/onionservices/content/netError/onionNetError.js b/browser/components/onionservices/content/netError/onionNetError.js
new file mode 100644
index 000000000000..8fabb3f38eb7
--- /dev/null
+++ b/browser/components/onionservices/content/netError/onionNetError.js
@@ -0,0 +1,244 @@
+// Copyright (c) 2020, The Tor Project, Inc.
+
+"use strict";
+
+/* eslint-env mozilla/frame-script */
+
+var OnionServicesAboutNetError = {
+ _selector: {
+ header: ".title-text",
+ longDesc: "#errorLongDesc",
+ learnMoreContainer: "#learnMoreContainer",
+ learnMoreLink: "#learnMoreLink",
+ contentContainer: "#errorLongContent",
+ tryAgainButtonContainer: "#netErrorButtonContainer",
+ },
+ _status: {
+ ok: "ok",
+ error: "error",
+ },
+
+ _diagramInfoMap: undefined,
+
+ // Public functions (called from outside this file).
+ //
+ // This initPage() function may need to be updated if the structure of
+ // browser/base/content/aboutNetError.xhtml changes. Specifically, it
+ // references the following elements:
+ // query string parameter e
+ // class title-text
+ // id errorLongDesc
+ // id learnMoreContainer
+ // id learnMoreLink
+ // id errorLongContent
+ initPage(aDoc) {
+ const searchParams = new URLSearchParams(aDoc.documentURI.split("?")[1]);
+ const err = searchParams.get("e");
+
+ const errPrefix = "onionServices.";
+ const errName = err.substring(errPrefix.length);
+
+ this._strings = RPMGetTorStrings();
+
+ const stringsObj = this._strings[errName];
+ if (!stringsObj) {
+ return;
+ }
+
+ this._insertStylesheet(aDoc);
+
+ const pageTitle = stringsObj.pageTitle;
+ const header = stringsObj.header;
+ const longDescription = stringsObj.longDescription; // optional
+ const learnMoreURL = stringsObj.learnMoreURL;
+
+ if (pageTitle) {
+ aDoc.title = pageTitle;
+ }
+
+ if (header) {
+ const headerElem = aDoc.querySelector(this._selector.header);
+ if (headerElem) {
+ headerElem.textContent = header;
+ }
+ }
+
+ const ld = aDoc.querySelector(this._selector.longDesc);
+ if (ld) {
+ if (longDescription) {
+ const hexErr = this._hexErrorFromName(errName);
+ ld.textContent = longDescription.replace("%S", hexErr);
+ } else {
+ // This onion service error does not have a long description. Since
+ // it is set to a generic error string by the code in
+ // browser/base/content/aboutNetError.js, hide it here.
+ ld.style.display = "none";
+ }
+ }
+
+ if (learnMoreURL) {
+ const lmContainer = aDoc.querySelector(this._selector.learnMoreContainer);
+ if (lmContainer) {
+ lmContainer.style.display = "block";
+ }
+ const lmLink = lmContainer.querySelector(this._selector.learnMoreLink);
+ if (lmLink) {
+ lmLink.setAttribute("href", learnMoreURL);
+ }
+ }
+
+ // Remove the "Try Again" button if the user made a typo in the .onion
+ // address since it is not useful in that case.
+ if (errName === "badAddress") {
+ const tryAgainButton = aDoc.querySelector(
+ this._selector.tryAgainButtonContainer
+ );
+ if (tryAgainButton) {
+ tryAgainButton.style.display = "none";
+ }
+ }
+
+ this._insertDiagram(aDoc, errName);
+ }, // initPage()
+
+ _insertStylesheet(aDoc) {
+ const url =
+ "chrome://browser/content/onionservices/netError/onionNetError.css";
+ let linkElem = aDoc.createElement("link");
+ linkElem.rel = "stylesheet";
+ linkElem.href = url;
+ linkElem.type = "text/css";
+ aDoc.head.appendChild(linkElem);
+ },
+
+ _insertDiagram(aDoc, aErrorName) {
+ // The onion error diagram consists of a grid of div elements.
+ // The first row contains three images (Browser, Network, Onionsite) and
+ // the second row contains labels for the images that are in the first row.
+ // The _diagramInfoMap describes for each type of onion service error
+ // whether a small ok or error status icon is overlaid on top of the main
+ // Browser/Network/Onionsite images.
+ if (!this._diagramInfoMap) {
+ this._diagramInfoMap = new Map();
+ this._diagramInfoMap.set("descNotFound", {
+ browser: this._status.ok,
+ network: this._status.ok,
+ onionSite: this._status.error,
+ });
+ this._diagramInfoMap.set("descInvalid", {
+ browser: this._status.ok,
+ network: this._status.error,
+ });
+ this._diagramInfoMap.set("introFailed", {
+ browser: this._status.ok,
+ network: this._status.error,
+ });
+ this._diagramInfoMap.set("rendezvousFailed", {
+ browser: this._status.ok,
+ network: this._status.error,
+ });
+ this._diagramInfoMap.set("clientAuthMissing", {
+ browser: this._status.error,
+ });
+ this._diagramInfoMap.set("clientAuthIncorrect", {
+ browser: this._status.error,
+ });
+ this._diagramInfoMap.set("badAddress", {
+ browser: this._status.error,
+ });
+ this._diagramInfoMap.set("introTimedOut", {
+ browser: this._status.ok,
+ network: this._status.error,
+ });
+ }
+
+ const diagramInfo = this._diagramInfoMap.get(aErrorName);
+
+ const container = this._createDiv(aDoc, "onionErrorDiagramContainer");
+ const imageClass = "onionErrorImage";
+
+ const browserImage = this._createDiv(
+ aDoc,
+ "onionErrorBrowserImage",
+ imageClass,
+ container
+ );
+ if (diagramInfo && diagramInfo.browser) {
+ browserImage.setAttribute("status", diagramInfo.browser);
+ }
+
+ const networkImage = this._createDiv(
+ aDoc,
+ "onionErrorNetworkImage",
+ imageClass,
+ container
+ );
+ if (diagramInfo && diagramInfo.network) {
+ networkImage.setAttribute("status", diagramInfo.network);
+ }
+
+ const onionSiteImage = this._createDiv(
+ aDoc,
+ "onionErrorOnionSiteImage",
+ imageClass,
+ container
+ );
+ if (diagramInfo && diagramInfo.onionSite) {
+ onionSiteImage.setAttribute("status", diagramInfo.onionSite);
+ }
+
+ let labelDiv = this._createDiv(aDoc, undefined, undefined, container);
+ labelDiv.textContent = this._strings.errorPage.browser;
+ labelDiv = this._createDiv(aDoc, undefined, undefined, container);
+ labelDiv.textContent = this._strings.errorPage.network;
+ labelDiv = this._createDiv(aDoc, undefined, undefined, container);
+ labelDiv.textContent = this._strings.errorPage.onionSite;
+
+ const contentContainer = aDoc.querySelector(
+ this._selector.contentContainer
+ );
+ if (contentContainer) {
+ contentContainer.insertBefore(container, contentContainer.firstChild);
+ }
+ }, // _insertDiagram()
+
+ _createDiv(aDoc, aID, aClass, aParentElem) {
+ const div = aDoc.createElement("div");
+ if (aID) {
+ div.id = aID;
+ }
+ if (aClass) {
+ div.setAttribute("class", aClass);
+ }
+ if (aParentElem) {
+ aParentElem.appendChild(div);
+ }
+
+ return div;
+ },
+
+ _hexErrorFromName(aErrorName) {
+ // We do not have access to the original Tor SOCKS error code here, so
+ // perform a reverse mapping from the error name.
+ switch (aErrorName) {
+ case "descNotFound":
+ return "0xF0";
+ case "descInvalid":
+ return "0xF1";
+ case "introFailed":
+ return "0xF2";
+ case "rendezvousFailed":
+ return "0xF3";
+ case "clientAuthMissing":
+ return "0xF4";
+ case "clientAuthIncorrect":
+ return "0xF5";
+ case "badAddress":
+ return "0xF6";
+ case "introTimedOut":
+ return "0xF7";
+ }
+
+ return "";
+ },
+};
diff --git a/browser/components/onionservices/content/netError/onionsite.svg b/browser/components/onionservices/content/netError/onionsite.svg
new file mode 100644
index 000000000000..1f2777e6acc7
--- /dev/null
+++ b/browser/components/onionservices/content/netError/onionsite.svg
@@ -0,0 +1,7 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="70" height="63" viewBox="0 0 70 63">
+ <g fill="context-fill" fill-opacity="context-fill-opacity">
+ <path d="M64.0 2.0C64.0 2.0 4.0 2.0 4.0 2.0C2.8954305 2.0 2.0 2.81148389 2.0 3.8125C2.0 3.8125 2.0 58.1875 2.0 58.1875C2.0 59.1885161 2.8954305 60.0 4.0 60.0C4.0 60.0 36.0 60.0 36.0 60.0C36.0 60.0 36.0 56.375 36.0 56.375C36.0 56.375 6.0 56.375 6.0 56.375C6.0 56.375 6.0 41.875 6.0 41.875C6.0 41.875 38.0 41.875 38.0 41.875C38.0 41.875 38.0 38.25 38.0 38.25C38.0 38.25 6.0 38.25 6.0 38.25C6.0 38.25 6.0 23.75 6.0 23.75C6.0 23.75 62.0 23.75 62.0 23.75C62.0 23.75 62.0 36.4375 62.0 36.4375C62.0 36.4375 66.0 36.4375 66.0 36.4375C66.0 36.4375 66.0 3.8125 66.0 3.8125C66.0 2.81148389 65.1045695 2.0 64.0 2.0C64.0 2.0 64.0 2.0 64.0 2.0M62.0 20.125C62.0 20.125 6.0 20.125 6.0 20.125C6.0 20.125 6.0 5.625 6.0 5.625C6.0 5.625 62.0 5.625 62.0 5.625C62.0 5.625 62.0 20.125 62.0 20.125C62.0 20.125 62.0 20.125 62.0 20.125" />
+ <path d="M24.0 47.0C24.0 47.0 24.0 51.0 24.0 51.0C24.0 51.0 20.0 51.0 20.0 51.0C20.0 51.0 20.0 47.0 20.0 47.0C20.0 47.0 24.0 47.0 24.0 47.0C24.0 47.0 24.0 47.0 24.0 47.0M16.0 47.0C16.0 47.0 16.0 51.0 16.0 51.0C16.0 51.0 12.0 51.0 12.0 51.0C12.0 51.0 12.0 47.0 12.0 47.0C12.0 47.0 16.0 47.0 16.0 47.0C16.0 47.0 16.0 47.0 16.0 47.0M56.0 29.0C56.0 29.0 56.0 33.0 56.0 33.0C56.0 33.0 52.0 33.0 52.0 33.0C52.0 33.0 52.0 29.0 52.0 29.0C52.0 29.0 56.0 29.0 56.0 29.0C56.0 29.0 56.0 29.0 56.0 29.0M48.0 29.0C48.0 29.0 48.0 33.0 48.0 33.0C48.0 33.0 12.0 33.0 12.0 33.0C12.0 33.0 12.0 29.0 12.0 29.0C12.0 29.0 48.0 29.0 48.0 29.0C48.0 29.0 48.0 29.0 48.0 29.0M22.0 11.0C22.0 11.0 22.0 15.0 22.0 15.0C22.0 15.0 10.0 15.0 10.0 15.0C10.0 15.0 10.0 11.0 10.0 11.0C10.0 11.0 22.0 11.0 22.0 11.0C22.0 11.0 22.0 11.0 22.0 11.0M70.0 0.0C70.0 0.0 70.0 36.5 70.0 36.5C70.0 36.5 65.0 36.5 65.0 36.5C65.0 36.5 65.0 4.5 65.0 4.5C65.0 4.5 5.0 4.5 5.0 4.5C5.0 4.5 5.0 58.5 5.0 58.5C5.0 58.5 36.0 58.5 36.0 58.5C36.0 58
.5 36.0 63.0 36.0 63.0C36.0 63.0 0.0 63.0 0.0 63.0C0.0 63.0 0.0 0.0 0.0 0.0C0.0 0.0 70.0 0.0 70.0 0.0C70.0 0.0 70.0 0.0 70.0 0.0M32.0 47.0C32.0 47.0 32.0 51.0 32.0 51.0C32.0 51.0 28.0 51.0 28.0 51.0C28.0 51.0 28.0 47.0 28.0 47.0C28.0 47.0 32.0 47.0 32.0 47.0C32.0 47.0 32.0 47.0 32.0 47.0M54.0 11.0C54.0 11.0 54.0 15.0 54.0 15.0C54.0 15.0 50.0 15.0 50.0 15.0C50.0 15.0 50.0 11.0 50.0 11.0C50.0 11.0 54.0 11.0 54.0 11.0C54.0 11.0 54.0 11.0 54.0 11.0M46.0 11.0C46.0 11.0 46.0 15.0 46.0 15.0C46.0 15.0 42.0 15.0 42.0 15.0C42.0 15.0 42.0 11.0 42.0 11.0C42.0 11.0 46.0 11.0 46.0 11.0C46.0 11.0 46.0 11.0 46.0 11.0M38.0 11.0C38.0 11.0 38.0 15.0 38.0 15.0C38.0 15.0 34.0 15.0 34.0 15.0C34.0 15.0 34.0 11.0 34.0 11.0C34.0 11.0 38.0 11.0 38.0 11.0C38.0 11.0 38.0 11.0 38.0 11.0M30.0 11.0C30.0 11.0 30.0 15.0 30.0 15.0C30.0 15.0 26.0 15.0 26.0 15.0C26.0 15.0 26.0 11.0 26.0 11.0C26.0 11.0 30.0 11.0 30.0 11.0C30.0 11.0 30.0 11.0 30.0 11.0" />
+ <path d="M61.0 46.0C61.0 46.0 59.0 46.0 59.0 46.0C59.0 46.0 59.0 40.0 59.0 40.0C59.0 38.8954305 58.1045695 38.0 57.0 38.0C57.0 38.0 49.0 38.0 49.0 38.0C47.8954305 38.0 47.0 38.8954305 47.0 40.0C47.0 40.0 47.0 46.0 47.0 46.0C47.0 46.0 45.0 46.0 45.0 46.0C43.8954305 46.0 43.0 46.8954305 43.0 48.0C43.0 48.0 43.0 60.0 43.0 60.0C43.0 61.1045695 43.8954305 62.0 45.0 62.0C45.0 62.0 61.0 62.0 61.0 62.0C62.1045695 62.0 63.0 61.1045695 63.0 60.0C63.0 60.0 63.0 48.0 63.0 48.0C63.0 46.8954305 62.1045695 46.0 61.0 46.0C61.0 46.0 61.0 46.0 61.0 46.0M51.0 42.0C51.0 42.0 55.0 42.0 55.0 42.0C55.0 42.0 55.0 46.0 55.0 46.0C55.0 46.0 51.0 46.0 51.0 46.0C51.0 46.0 51.0 42.0 51.0 42.0C51.0 42.0 51.0 42.0 51.0 42.0M59.0 58.0C59.0 58.0 47.0 58.0 47.0 58.0C47.0 58.0 47.0 50.0 47.0 50.0C47.0 50.0 59.0 50.0 59.0 50.0C59.0 50.0 59.0 58.0 59.0 58.0C59.0 58.0 59.0 58.0 59.0 58.0" />
+ </g>
+</svg>
diff --git a/browser/components/onionservices/content/onionservices.css b/browser/components/onionservices/content/onionservices.css
new file mode 100644
index 000000000000..e2621ec8266d
--- /dev/null
+++ b/browser/components/onionservices/content/onionservices.css
@@ -0,0 +1,69 @@
+/* Copyright (c) 2020, The Tor Project, Inc. */
+
+@namespace html url("http://www.w3.org/1999/xhtml");
+
+html|*#tor-clientauth-notification-onionname {
+ font-weight: bold;
+}
+
+html|*#tor-clientauth-notification-key {
+ box-sizing: border-box;
+ width: 100%;
+ margin-top: 15px;
+ padding: 6px;
+}
+
+/* Start of rules adapted from
+ * browser/components/newtab/css/activity-stream-mac.css (linux and windows
+ * use the same rules).
+ */
+html|*#tor-clientauth-notification-key.invalid {
+ border: 1px solid #D70022;
+ box-shadow: 0 0 0 1px #D70022, 0 0 0 4px rgba(215, 0, 34, 0.3);
+}
+
+html|*#tor-clientauth-warning {
+ display: inline-block;
+ animation: fade-up-tt 450ms;
+ background: #D70022;
+ border-radius: 2px;
+ color: #FFF;
+ inset-inline-start: 3px;
+ padding: 5px 12px;
+ position: relative;
+ top: 6px;
+ z-index: 1;
+}
+
+html|*#tor-clientauth-warning[hidden] {
+ display: none;
+}
+
+html|*#tor-clientauth-warning::before {
+ background: #D70022;
+ bottom: -8px;
+ content: '.';
+ height: 16px;
+ inset-inline-start: 12px;
+ position: absolute;
+ text-indent: -999px;
+ top: -7px;
+ transform: rotate(45deg);
+ white-space: nowrap;
+ width: 16px;
+ z-index: -1;
+}
+
+@keyframes fade-up-tt {
+ 0% {
+ opacity: 0;
+ transform: translateY(15px);
+ }
+ 100% {
+ opacity: 1;
+ transform: translateY(0);
+ }
+}
+/* End of rules adapted from
+ * browser/components/newtab/css/activity-stream-mac.css
+ */
diff --git a/browser/components/onionservices/content/savedKeysDialog.js b/browser/components/onionservices/content/savedKeysDialog.js
new file mode 100644
index 000000000000..b1376bbabe85
--- /dev/null
+++ b/browser/components/onionservices/content/savedKeysDialog.js
@@ -0,0 +1,259 @@
+// Copyright (c) 2020, The Tor Project, Inc.
+
+"use strict";
+
+ChromeUtils.defineModuleGetter(
+ this,
+ "TorStrings",
+ "resource:///modules/TorStrings.jsm"
+);
+
+ChromeUtils.defineModuleGetter(
+ this,
+ "controller",
+ "resource://torbutton/modules/tor-control-port.js"
+);
+
+var gOnionServicesSavedKeysDialog = {
+ selector: {
+ dialog: "#onionservices-savedkeys-dialog",
+ intro: "#onionservices-savedkeys-intro",
+ tree: "#onionservices-savedkeys-tree",
+ onionSiteCol: "#onionservices-savedkeys-siteCol",
+ onionKeyCol: "#onionservices-savedkeys-keyCol",
+ errorIcon: "#onionservices-savedkeys-errorIcon",
+ errorMessage: "#onionservices-savedkeys-errorMessage",
+ removeButton: "#onionservices-savedkeys-remove",
+ removeAllButton: "#onionservices-savedkeys-removeall",
+ },
+
+ _tree: undefined,
+ _isBusy: false, // true when loading data, deleting a key, etc.
+
+ // Public functions (called from outside this file).
+ async deleteSelectedKeys() {
+ this._setBusyState(true);
+
+ const indexesToDelete = [];
+ const count = this._tree.view.selection.getRangeCount();
+ for (let i = 0; i < count; ++i) {
+ const minObj = {};
+ const maxObj = {};
+ this._tree.view.selection.getRangeAt(i, minObj, maxObj);
+ for (let idx = minObj.value; idx <= maxObj.value; ++idx) {
+ indexesToDelete.push(idx);
+ }
+ }
+
+ if (indexesToDelete.length > 0) {
+ const controllerFailureMsg =
+ TorStrings.onionServices.authPreferences.failedToRemoveKey;
+ try {
+ const torController = controller(aError => {
+ this._showError(controllerFailureMsg);
+ });
+
+ // Remove in reverse index order to avoid issues caused by index changes.
+ for (let i = indexesToDelete.length - 1; i >= 0; --i) {
+ await this._deleteOneKey(torController, indexesToDelete[i]);
+ }
+ } catch (e) {
+ if (e.torMessage) {
+ this._showError(e.torMessage);
+ } else {
+ this._showError(controllerFailureMsg);
+ }
+ }
+ }
+
+ this._setBusyState(false);
+ },
+
+ async deleteAllKeys() {
+ this._tree.view.selection.selectAll();
+ await this.deleteSelectedKeys();
+ },
+
+ updateButtonsState() {
+ const haveSelection = this._tree.view.selection.getRangeCount() > 0;
+ const dialog = document.querySelector(this.selector.dialog);
+ const removeSelectedBtn = dialog.querySelector(this.selector.removeButton);
+ removeSelectedBtn.disabled = this._isBusy || !haveSelection;
+ const removeAllBtn = dialog.querySelector(this.selector.removeAllButton);
+ removeAllBtn.disabled = this._isBusy || this.rowCount === 0;
+ },
+
+ // Private functions.
+ _onLoad() {
+ document.mozSubdialogReady = this._init();
+ },
+
+ async _init() {
+ await this._populateXUL();
+
+ window.addEventListener("keypress", this._onWindowKeyPress.bind(this));
+
+ // We don't use await here because we want _loadSavedKeys() to run
+ // in the background and not block loading of this dialog.
+ this._loadSavedKeys();
+ },
+
+ async _populateXUL() {
+ const dialog = document.querySelector(this.selector.dialog);
+ const authPrefStrings = TorStrings.onionServices.authPreferences;
+ dialog.setAttribute("title", authPrefStrings.dialogTitle);
+
+ let elem = dialog.querySelector(this.selector.intro);
+ elem.textContent = authPrefStrings.dialogIntro;
+
+ elem = dialog.querySelector(this.selector.onionSiteCol);
+ elem.setAttribute("label", authPrefStrings.onionSite);
+
+ elem = dialog.querySelector(this.selector.onionKeyCol);
+ elem.setAttribute("label", authPrefStrings.onionKey);
+
+ elem = dialog.querySelector(this.selector.removeButton);
+ elem.setAttribute("label", authPrefStrings.remove);
+
+ elem = dialog.querySelector(this.selector.removeAllButton);
+ elem.setAttribute("label", authPrefStrings.removeAll);
+
+ this._tree = dialog.querySelector(this.selector.tree);
+ },
+
+ async _loadSavedKeys() {
+ const controllerFailureMsg =
+ TorStrings.onionServices.authPreferences.failedToGetKeys;
+ this._setBusyState(true);
+
+ try {
+ this._tree.view = this;
+
+ const torController = controller(aError => {
+ this._showError(controllerFailureMsg);
+ });
+
+ const keyInfoList = await torController.onionAuthViewKeys();
+ if (keyInfoList) {
+ // Filter out temporary keys.
+ this._keyInfoList = keyInfoList.filter(aKeyInfo => {
+ if (!aKeyInfo.Flags) {
+ return false;
+ }
+
+ const flags = aKeyInfo.Flags.split(",");
+ return flags.includes("Permanent");
+ });
+
+ // Sort by the .onion address.
+ this._keyInfoList.sort((aObj1, aObj2) => {
+ const hsAddr1 = aObj1.hsAddress.toLowerCase();
+ const hsAddr2 = aObj2.hsAddress.toLowerCase();
+ if (hsAddr1 < hsAddr2) {
+ return -1;
+ }
+ return hsAddr1 > hsAddr2 ? 1 : 0;
+ });
+ }
+
+ // Render the tree content.
+ this._tree.rowCountChanged(0, this.rowCount);
+ } catch (e) {
+ if (e.torMessage) {
+ this._showError(e.torMessage);
+ } else {
+ this._showError(controllerFailureMsg);
+ }
+ }
+
+ this._setBusyState(false);
+ },
+
+ // This method may throw; callers should catch errors.
+ async _deleteOneKey(aTorController, aIndex) {
+ const keyInfoObj = this._keyInfoList[aIndex];
+ await aTorController.onionAuthRemove(keyInfoObj.hsAddress);
+ this._tree.view.selection.clearRange(aIndex, aIndex);
+ this._keyInfoList.splice(aIndex, 1);
+ this._tree.rowCountChanged(aIndex + 1, -1);
+ },
+
+ _setBusyState(aIsBusy) {
+ this._isBusy = aIsBusy;
+ this.updateButtonsState();
+ },
+
+ _onWindowKeyPress(event) {
+ if (event.keyCode === KeyEvent.DOM_VK_ESCAPE) {
+ window.close();
+ } else if (event.keyCode === KeyEvent.DOM_VK_DELETE) {
+ this.deleteSelectedKeys();
+ }
+ },
+
+ _showError(aMessage) {
+ const dialog = document.querySelector(this.selector.dialog);
+ const errorIcon = dialog.querySelector(this.selector.errorIcon);
+ errorIcon.style.visibility = aMessage ? "visible" : "hidden";
+ const errorDesc = dialog.querySelector(this.selector.errorMessage);
+ errorDesc.textContent = aMessage ? aMessage : "";
+ },
+
+ // XUL tree widget view implementation.
+ get rowCount() {
+ return this._keyInfoList ? this._keyInfoList.length : 0;
+ },
+
+ getCellText(aRow, aCol) {
+ let val = "";
+ if (this._keyInfoList && aRow < this._keyInfoList.length) {
+ const keyInfo = this._keyInfoList[aRow];
+ if (aCol.id.endsWith("-siteCol")) {
+ val = keyInfo.hsAddress;
+ } else if (aCol.id.endsWith("-keyCol")) {
+ val = keyInfo.typeAndKey;
+ // Omit keyType because it is always "x25519".
+ const idx = val.indexOf(":");
+ if (idx > 0) {
+ val = val.substring(idx + 1);
+ }
+ }
+ }
+
+ return val;
+ },
+
+ isSeparator(index) {
+ return false;
+ },
+
+ isSorted() {
+ return false;
+ },
+
+ isContainer(index) {
+ return false;
+ },
+
+ setTree(tree) {},
+
+ getImageSrc(row, column) {},
+
+ getCellValue(row, column) {},
+
+ cycleHeader(column) {},
+
+ getRowProperties(row) {
+ return "";
+ },
+
+ getColumnProperties(column) {
+ return "";
+ },
+
+ getCellProperties(row, column) {
+ return "";
+ },
+};
+
+window.addEventListener("load", () => gOnionServicesSavedKeysDialog._onLoad());
diff --git a/browser/components/onionservices/content/savedKeysDialog.xhtml b/browser/components/onionservices/content/savedKeysDialog.xhtml
new file mode 100644
index 000000000000..3db9bb05ea82
--- /dev/null
+++ b/browser/components/onionservices/content/savedKeysDialog.xhtml
@@ -0,0 +1,42 @@
+<?xml version="1.0"?>
+<!-- Copyright (c) 2020, The Tor Project, Inc. -->
+
+<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
+<?xml-stylesheet href="chrome://browser/skin/preferences/preferences.css" type="text/css"?>
+<?xml-stylesheet href="chrome://browser/content/onionservices/authPreferences.css" type="text/css"?>
+
+<window id="onionservices-savedkeys-dialog"
+ windowtype="OnionServices:SavedKeys"
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+ style="width: 45em;">
+
+ <script src="chrome://browser/content/onionservices/savedKeysDialog.js"/>
+
+ <vbox id="onionservices-savedkeys" class="contentPane" flex="1">
+ <label id="onionservices-savedkeys-intro"
+ control="onionservices-savedkeys-tree"/>
+ <separator class="thin"/>
+ <tree id="onionservices-savedkeys-tree" flex="1" hidecolumnpicker="true"
+ width="750"
+ style="height: 20em;"
+ onselect="gOnionServicesSavedKeysDialog.updateButtonsState();">
+ <treecols>
+ <treecol id="onionservices-savedkeys-siteCol" flex="1" persist="width"/>
+ <splitter class="tree-splitter"/>
+ <treecol id="onionservices-savedkeys-keyCol" flex="1" persist="width"/>
+ </treecols>
+ <treechildren/>
+ </tree>
+ <hbox id="onionservices-savedkeys-errorContainer" align="baseline" flex="1">
+ <image id="onionservices-savedkeys-errorIcon"/>
+ <description id="onionservices-savedkeys-errorMessage" flex="1"/>
+ </hbox>
+ <separator class="thin"/>
+ <hbox id="onionservices-savedkeys-buttons">
+ <button id="onionservices-savedkeys-remove" disabled="true"
+ oncommand="gOnionServicesSavedKeysDialog.deleteSelectedKeys();"/>
+ <button id="onionservices-savedkeys-removeall"
+ oncommand="gOnionServicesSavedKeysDialog.deleteAllKeys();"/>
+ </hbox>
+ </vbox>
+</window>
diff --git a/browser/components/onionservices/jar.mn b/browser/components/onionservices/jar.mn
new file mode 100644
index 000000000000..9d6ce88d1841
--- /dev/null
+++ b/browser/components/onionservices/jar.mn
@@ -0,0 +1,9 @@
+browser.jar:
+ content/browser/onionservices/authPreferences.css (content/authPreferences.css)
+ content/browser/onionservices/authPreferences.js (content/authPreferences.js)
+ content/browser/onionservices/authPrompt.js (content/authPrompt.js)
+ content/browser/onionservices/authUtil.jsm (content/authUtil.jsm)
+ content/browser/onionservices/netError/ (content/netError/*)
+ content/browser/onionservices/onionservices.css (content/onionservices.css)
+ content/browser/onionservices/savedKeysDialog.js (content/savedKeysDialog.js)
+ content/browser/onionservices/savedKeysDialog.xhtml (content/savedKeysDialog.xhtml)
diff --git a/browser/components/onionservices/moz.build b/browser/components/onionservices/moz.build
new file mode 100644
index 000000000000..7e103239c8d6
--- /dev/null
+++ b/browser/components/onionservices/moz.build
@@ -0,0 +1 @@
+JAR_MANIFESTS += ['jar.mn']
diff --git a/browser/components/preferences/preferences.xhtml b/browser/components/preferences/preferences.xhtml
index 2a99400bfb70..b09808e83c45 100644
--- a/browser/components/preferences/preferences.xhtml
+++ b/browser/components/preferences/preferences.xhtml
@@ -12,6 +12,7 @@
<?xml-stylesheet href="chrome://browser/skin/preferences/search.css"?>
<?xml-stylesheet href="chrome://browser/skin/preferences/containers.css"?>
<?xml-stylesheet href="chrome://browser/skin/preferences/privacy.css"?>
+<?xml-stylesheet href="chrome://browser/content/onionservices/authPreferences.css"?>
<?xml-stylesheet href="chrome://browser/content/securitylevel/securityLevelPreferences.css"?>
<?xml-stylesheet href="chrome://browser/content/torpreferences/torPreferences.css"?>
diff --git a/browser/components/preferences/privacy.inc.xhtml b/browser/components/preferences/privacy.inc.xhtml
index f36145ea80d4..eb7587afa0e1 100644
--- a/browser/components/preferences/privacy.inc.xhtml
+++ b/browser/components/preferences/privacy.inc.xhtml
@@ -477,6 +477,8 @@
<label id="fips-desc" hidden="true" data-l10n-id="forms-master-pw-fips-desc"></label>
</groupbox>
+#include ../onionservices/content/authPreferences.inc.xhtml
+
<!-- The form autofill section is inserted in to this box
after the form autofill extension has initialized. -->
<groupbox id="formAutofillGroupBox"
diff --git a/browser/components/preferences/privacy.js b/browser/components/preferences/privacy.js
index 35e1fda9f96b..41dda96a14de 100644
--- a/browser/components/preferences/privacy.js
+++ b/browser/components/preferences/privacy.js
@@ -77,6 +77,12 @@ XPCOMUtils.defineLazyGetter(this, "AlertsServiceDND", function() {
}
});
+XPCOMUtils.defineLazyScriptGetter(
+ this,
+ ["OnionServicesAuthPreferences"],
+ "chrome://browser/content/onionservices/authPreferences.js"
+);
+
// TODO: module import via ChromeUtils.defineModuleGetter
XPCOMUtils.defineLazyScriptGetter(
this,
@@ -434,6 +440,7 @@ var gPrivacyPane = {
this.trackingProtectionReadPrefs();
this.networkCookieBehaviorReadPrefs();
this._initTrackingProtectionExtensionControl();
+ OnionServicesAuthPreferences.init();
this._initSecurityLevel();
Services.telemetry.setEventRecordingEnabled("pwmgr", true);
diff --git a/browser/themes/shared/notification-icons.inc.css b/browser/themes/shared/notification-icons.inc.css
index f17ddae9dc79..979ae9482244 100644
--- a/browser/themes/shared/notification-icons.inc.css
+++ b/browser/themes/shared/notification-icons.inc.css
@@ -117,6 +117,9 @@
list-style-image: url(chrome://browser/skin/notification-icons/indexedDB.svg);
}
+/* Reuse Firefox's login (key) icon for the Tor onion services auth. prompt */
+.popup-notification-icon[popupid="tor-clientauth"],
+.tor-clientauth-icon,
.popup-notification-icon[popupid="password"],
.login-icon {
list-style-image: url(chrome://browser/skin/login.svg);
diff --git a/docshell/base/nsDocShell.cpp b/docshell/base/nsDocShell.cpp
index 22eb5c4556f6..8731e44dd4eb 100644
--- a/docshell/base/nsDocShell.cpp
+++ b/docshell/base/nsDocShell.cpp
@@ -3536,6 +3536,7 @@ nsDocShell::DisplayLoadError(nsresult aError, nsIURI* aURI,
}
} else {
// Errors requiring simple formatting
+ bool isOnionAuthError = false;
switch (aError) {
case NS_ERROR_MALFORMED_URI:
// URI is malformed
@@ -3618,10 +3619,44 @@ nsDocShell::DisplayLoadError(nsresult aError, nsIURI* aURI,
// HTTP/2 or HTTP/3 stack detected a protocol error
error = "networkProtocolError";
break;
-
+ case NS_ERROR_TOR_ONION_SVC_NOT_FOUND:
+ error = "onionServices.descNotFound";
+ break;
+ case NS_ERROR_TOR_ONION_SVC_IS_INVALID:
+ error = "onionServices.descInvalid";
+ break;
+ case NS_ERROR_TOR_ONION_SVC_INTRO_FAILED:
+ error = "onionServices.introFailed";
+ break;
+ case NS_ERROR_TOR_ONION_SVC_REND_FAILED:
+ error = "onionServices.rendezvousFailed";
+ break;
+ case NS_ERROR_TOR_ONION_SVC_MISSING_CLIENT_AUTH:
+ error = "onionServices.clientAuthMissing";
+ isOnionAuthError = true;
+ break;
+ case NS_ERROR_TOR_ONION_SVC_BAD_CLIENT_AUTH:
+ error = "onionServices.clientAuthIncorrect";
+ isOnionAuthError = true;
+ break;
+ case NS_ERROR_TOR_ONION_SVC_BAD_ADDRESS:
+ error = "onionServices.badAddress";
+ break;
+ case NS_ERROR_TOR_ONION_SVC_INTRO_TIMEDOUT:
+ error = "onionServices.introTimedOut";
+ break;
default:
break;
}
+
+ // The presence of aFailedChannel indicates that we arrived here due to a
+ // failed connection attempt. Note that we will arrive here a second time
+ // if the user cancels the Tor client auth prompt, but in that case we
+ // will not have a failed channel and therefore we will not prompt again.
+ if (isOnionAuthError && aFailedChannel) {
+ // Display about:blank while the Tor client auth prompt is open.
+ errorPage.AssignLiteral("blank");
+ }
}
// If the HTTPS-Only Mode upgraded this request and the upgrade might have
@@ -3710,6 +3745,20 @@ nsDocShell::DisplayLoadError(nsresult aError, nsIURI* aURI,
nsAutoString str;
rv =
stringBundle->FormatStringFromName(errorDescriptionID, formatStrs, str);
+ if (NS_FAILED(rv)) {
+ // As a fallback, check torbutton.properties for the error string.
+ const char bundleURL[] = "chrome://torbutton/locale/torbutton.properties";
+ nsCOMPtr<nsIStringBundleService> stringBundleService =
+ mozilla::services::GetStringBundleService();
+ if (stringBundleService) {
+ nsCOMPtr<nsIStringBundle> tbStringBundle;
+ if (NS_SUCCEEDED(stringBundleService->CreateBundle(
+ bundleURL, getter_AddRefs(tbStringBundle)))) {
+ rv = tbStringBundle->FormatStringFromName(errorDescriptionID,
+ formatStrs, str);
+ }
+ }
+ }
NS_ENSURE_SUCCESS(rv, rv);
messageStr.Assign(str);
}
@@ -6197,6 +6246,7 @@ nsresult nsDocShell::EndPageLoad(nsIWebProgress* aProgress,
aStatus == NS_ERROR_NET_INADEQUATE_SECURITY ||
aStatus == NS_ERROR_NET_HTTP2_SENT_GOAWAY ||
aStatus == NS_ERROR_NET_HTTP3_PROTOCOL_ERROR ||
+ NS_ERROR_GET_MODULE(aStatus) == NS_ERROR_MODULE_TOR ||
NS_ERROR_GET_MODULE(aStatus) == NS_ERROR_MODULE_SECURITY) {
// Errors to be shown for any frame
DisplayLoadError(aStatus, url, nullptr, aChannel);
@@ -7761,6 +7811,35 @@ nsresult nsDocShell::CreateContentViewer(const nsACString& aContentType,
FireOnLocationChange(this, aRequest, mCurrentURI, locationFlags);
}
+ // Arrange to show a Tor onion service client authentication prompt if
+ // appropriate.
+ if ((mLoadType == LOAD_ERROR_PAGE) && failedChannel) {
+ nsresult status = NS_OK;
+ if (NS_SUCCEEDED(failedChannel->GetStatus(&status)) &&
+ ((status == NS_ERROR_TOR_ONION_SVC_MISSING_CLIENT_AUTH) ||
+ (status == NS_ERROR_TOR_ONION_SVC_BAD_CLIENT_AUTH))) {
+ nsAutoCString onionHost;
+ failedURI->GetHost(onionHost);
+ const char* topic = (status == NS_ERROR_TOR_ONION_SVC_MISSING_CLIENT_AUTH)
+ ? "tor-onion-services-clientauth-missing"
+ : "tor-onion-services-clientauth-incorrect";
+ if (XRE_IsContentProcess()) {
+ nsCOMPtr<nsIBrowserChild> browserChild = GetBrowserChild();
+ if (browserChild) {
+ static_cast<BrowserChild*>(browserChild.get())
+ ->SendShowOnionServicesAuthPrompt(onionHost, nsCString(topic));
+ }
+ } else {
+ nsCOMPtr<nsPIDOMWindowOuter> browserWin = GetWindow();
+ nsCOMPtr<nsIObserverService> obsSvc = services::GetObserverService();
+ if (browserWin && obsSvc) {
+ obsSvc->NotifyObservers(browserWin, topic,
+ NS_ConvertUTF8toUTF16(onionHost).get());
+ }
+ }
+ }
+ }
+
return NS_OK;
}
diff --git a/dom/ipc/BrowserParent.cpp b/dom/ipc/BrowserParent.cpp
index dfd15c1fd17b..7749792cafb4 100644
--- a/dom/ipc/BrowserParent.cpp
+++ b/dom/ipc/BrowserParent.cpp
@@ -3941,6 +3941,27 @@ mozilla::ipc::IPCResult BrowserParent::RecvShowCanvasPermissionPrompt(
return IPC_OK();
}
+mozilla::ipc::IPCResult BrowserParent::RecvShowOnionServicesAuthPrompt(
+ const nsCString& aOnionName, const nsCString& aTopic) {
+ nsCOMPtr<nsIBrowser> browser =
+ mFrameElement ? mFrameElement->AsBrowser() : nullptr;
+ if (!browser) {
+ // If the tab is being closed, the browser may not be available.
+ // In this case we can ignore the request.
+ return IPC_OK();
+ }
+ nsCOMPtr<nsIObserverService> os = services::GetObserverService();
+ if (!os) {
+ return IPC_FAIL_NO_REASON(this);
+ }
+ nsresult rv = os->NotifyObservers(browser, aTopic.get(),
+ NS_ConvertUTF8toUTF16(aOnionName).get());
+ if (NS_FAILED(rv)) {
+ return IPC_FAIL_NO_REASON(this);
+ }
+ return IPC_OK();
+}
+
mozilla::ipc::IPCResult BrowserParent::RecvVisitURI(nsIURI* aURI,
nsIURI* aLastVisitedURI,
const uint32_t& aFlags) {
diff --git a/dom/ipc/BrowserParent.h b/dom/ipc/BrowserParent.h
index 66509194edba..816945504b6c 100644
--- a/dom/ipc/BrowserParent.h
+++ b/dom/ipc/BrowserParent.h
@@ -763,6 +763,9 @@ class BrowserParent final : public PBrowserParent,
mozilla::ipc::IPCResult RecvShowCanvasPermissionPrompt(
const nsCString& aOrigin, const bool& aHideDoorHanger);
+ mozilla::ipc::IPCResult RecvShowOnionServicesAuthPrompt(
+ const nsCString& aOnionName, const nsCString& aTopic);
+
mozilla::ipc::IPCResult RecvSetSystemFont(const nsCString& aFontName);
mozilla::ipc::IPCResult RecvGetSystemFont(nsCString* aFontName);
diff --git a/dom/ipc/PBrowser.ipdl b/dom/ipc/PBrowser.ipdl
index ed31b32a4eb2..f36e2c6db353 100644
--- a/dom/ipc/PBrowser.ipdl
+++ b/dom/ipc/PBrowser.ipdl
@@ -592,6 +592,15 @@ parent:
bool aNeedCollectSHistory, uint32_t aFlushId,
bool aIsFinal, uint32_t aEpoch);
+ /**
+ * This function is used to notify the parent that it should display a
+ * onion services client authentication prompt.
+ *
+ * @param aOnionHost The hostname of the .onion that needs authentication.
+ * @param aTopic The reason for the prompt.
+ */
+ async ShowOnionServicesAuthPrompt(nsCString aOnionHost, nsCString aTopic);
+
child:
async NativeSynthesisResponse(uint64_t aObserverId, nsCString aResponse);
async FlushTabState(uint32_t aFlushId, bool aIsFinal);
diff --git a/js/xpconnect/src/xpc.msg b/js/xpconnect/src/xpc.msg
index d884c6a85999..31e5e75ba35c 100644
--- a/js/xpconnect/src/xpc.msg
+++ b/js/xpconnect/src/xpc.msg
@@ -253,5 +253,15 @@ XPC_MSG_DEF(NS_ERROR_FINGERPRINTING_URI , "The URI is fingerprinti
XPC_MSG_DEF(NS_ERROR_CRYPTOMINING_URI , "The URI is cryptomining")
XPC_MSG_DEF(NS_ERROR_SOCIALTRACKING_URI , "The URI is social tracking")
+/* Codes related to Tor */
+XPC_MSG_DEF(NS_ERROR_TOR_ONION_SVC_NOT_FOUND , "Tor onion service descriptor cannot be found")
+XPC_MSG_DEF(NS_ERROR_TOR_ONION_SVC_IS_INVALID , "Tor onion service descriptor is invalid")
+XPC_MSG_DEF(NS_ERROR_TOR_ONION_SVC_INTRO_FAILED , "Tor onion service introduction failed")
+XPC_MSG_DEF(NS_ERROR_TOR_ONION_SVC_REND_FAILED , "Tor onion service rendezvous failed")
+XPC_MSG_DEF(NS_ERROR_TOR_ONION_SVC_MISSING_CLIENT_AUTH, "Tor onion service missing client authorization")
+XPC_MSG_DEF(NS_ERROR_TOR_ONION_SVC_BAD_CLIENT_AUTH , "Tor onion service wrong client authorization")
+XPC_MSG_DEF(NS_ERROR_TOR_ONION_SVC_BAD_ADDRESS , "Tor onion service bad address")
+XPC_MSG_DEF(NS_ERROR_TOR_ONION_SVC_INTRO_TIMEDOUT , "Tor onion service introduction timed out")
+
/* Profile manager error codes */
XPC_MSG_DEF(NS_ERROR_DATABASE_CHANGED , "Flushing the profiles to disk would have overwritten changes made elsewhere.")
diff --git a/netwerk/base/nsSocketTransport2.cpp b/netwerk/base/nsSocketTransport2.cpp
index 7256280697c8..ce739e1f0de8 100644
--- a/netwerk/base/nsSocketTransport2.cpp
+++ b/netwerk/base/nsSocketTransport2.cpp
@@ -215,6 +215,12 @@ nsresult ErrorAccordingToNSPR(PRErrorCode errorCode) {
default:
if (psm::IsNSSErrorCode(errorCode)) {
rv = psm::GetXPCOMFromNSSError(errorCode);
+ } else {
+ // If we received a Tor extended error code via SOCKS, pass it through.
+ nsresult res = nsresult(errorCode);
+ if (NS_ERROR_GET_MODULE(res) == NS_ERROR_MODULE_TOR) {
+ rv = res;
+ }
}
break;
diff --git a/netwerk/socket/nsSOCKSIOLayer.cpp b/netwerk/socket/nsSOCKSIOLayer.cpp
index 6f2743ed5c71..57af13a7c026 100644
--- a/netwerk/socket/nsSOCKSIOLayer.cpp
+++ b/netwerk/socket/nsSOCKSIOLayer.cpp
@@ -1004,6 +1004,55 @@ PRStatus nsSOCKSSocketInfo::ReadV5ConnectResponseTop() {
"08, Address type not supported."));
c = PR_BAD_ADDRESS_ERROR;
break;
+ case 0xF0: // Tor SOCKS5_HS_NOT_FOUND
+ LOGERROR(
+ ("socks5: connect failed: F0,"
+ " Tor onion service descriptor can not be found."));
+ c = static_cast<uint32_t>(NS_ERROR_TOR_ONION_SVC_NOT_FOUND);
+ break;
+ case 0xF1: // Tor SOCKS5_HS_IS_INVALID
+ LOGERROR(
+ ("socks5: connect failed: F1,"
+ " Tor onion service descriptor is invalid."));
+ c = static_cast<uint32_t>(NS_ERROR_TOR_ONION_SVC_IS_INVALID);
+ break;
+ case 0xF2: // Tor SOCKS5_HS_INTRO_FAILED
+ LOGERROR(
+ ("socks5: connect failed: F2,"
+ " Tor onion service introduction failed."));
+ c = static_cast<uint32_t>(NS_ERROR_TOR_ONION_SVC_INTRO_FAILED);
+ break;
+ case 0xF3: // Tor SOCKS5_HS_REND_FAILED
+ LOGERROR(
+ ("socks5: connect failed: F3,"
+ " Tor onion service rendezvous failed."));
+ c = static_cast<uint32_t>(NS_ERROR_TOR_ONION_SVC_REND_FAILED);
+ break;
+ case 0xF4: // Tor SOCKS5_HS_MISSING_CLIENT_AUTH
+ LOGERROR(
+ ("socks5: connect failed: F4,"
+ " Tor onion service missing client authorization."));
+ c = static_cast<uint32_t>(NS_ERROR_TOR_ONION_SVC_MISSING_CLIENT_AUTH);
+ break;
+ case 0xF5: // Tor SOCKS5_HS_BAD_CLIENT_AUTH
+ LOGERROR(
+ ("socks5: connect failed: F5,"
+ " Tor onion service wrong client authorization."));
+ c = static_cast<uint32_t>(NS_ERROR_TOR_ONION_SVC_BAD_CLIENT_AUTH);
+ break;
+ case 0xF6: // Tor SOCKS5_HS_BAD_ADDRESS
+ LOGERROR(
+ ("socks5: connect failed: F6,"
+ " Tor onion service bad address."));
+ c = static_cast<uint32_t>(NS_ERROR_TOR_ONION_SVC_BAD_ADDRESS);
+ break;
+ case 0xF7: // Tor SOCKS5_HS_INTRO_TIMEDOUT
+ LOGERROR(
+ ("socks5: connect failed: F7,"
+ " Tor onion service introduction timed out."));
+ c = static_cast<uint32_t>(NS_ERROR_TOR_ONION_SVC_INTRO_TIMEDOUT);
+ break;
+
default:
LOGERROR(("socks5: connect failed."));
break;
diff --git a/toolkit/modules/PopupNotifications.jsm b/toolkit/modules/PopupNotifications.jsm
index d31f91ab00a5..6886c0b13c5d 100644
--- a/toolkit/modules/PopupNotifications.jsm
+++ b/toolkit/modules/PopupNotifications.jsm
@@ -406,6 +406,8 @@ PopupNotifications.prototype = {
* will be dismissed instead of removed after running the callback.
* - [optional] disabled (boolean): If this is true, the button
* will be disabled.
+ * - [optional] leaveOpen (boolean): If this is true, the notification
+ * will not be removed after running the callback.
* - [optional] disableHighlight (boolean): If this is true, the button
* will not apply the default highlight style.
* If null, the notification will have a default "OK" action button
@@ -1884,6 +1886,10 @@ PopupNotifications.prototype = {
this._dismiss();
return;
}
+
+ if (action.leaveOpen) {
+ return;
+ }
}
this._remove(notification);
diff --git a/toolkit/modules/RemotePageAccessManager.jsm b/toolkit/modules/RemotePageAccessManager.jsm
index 9734324cbd5f..eceaa7c857de 100644
--- a/toolkit/modules/RemotePageAccessManager.jsm
+++ b/toolkit/modules/RemotePageAccessManager.jsm
@@ -95,6 +95,7 @@ let RemotePageAccessManager = {
],
RPMPrefIsLocked: ["security.tls.version.min"],
RPMAddToHistogram: ["*"],
+ RPMGetTorStrings: ["*"],
},
"about:newinstall": {
RPMGetUpdateChannel: ["*"],
diff --git a/tools/lint/eslint/eslint-plugin-mozilla/lib/environments/frame-script.js b/tools/lint/eslint/eslint-plugin-mozilla/lib/environments/frame-script.js
index 28f5d864b0bd..cd0d6d4d3656 100644
--- a/tools/lint/eslint/eslint-plugin-mozilla/lib/environments/frame-script.js
+++ b/tools/lint/eslint/eslint-plugin-mozilla/lib/environments/frame-script.js
@@ -37,5 +37,6 @@ module.exports = {
RPMRecordTelemetryEvent: false,
RPMAddToHistogram: false,
RPMRemoveMessageListener: false,
+ RPMGetTorStrings: false,
},
};
diff --git a/xpcom/base/ErrorList.py b/xpcom/base/ErrorList.py
index 6b1a05a91b31..5f35cf7771f9 100755
--- a/xpcom/base/ErrorList.py
+++ b/xpcom/base/ErrorList.py
@@ -85,6 +85,7 @@ modules["URL_CLASSIFIER"] = Mod(42)
# ErrorResult gets its own module to reduce the chance of someone accidentally
# defining an error code matching one of the ErrorResult ones.
modules["ERRORRESULT"] = Mod(43)
+modules["TOR"] = Mod(44)
# NS_ERROR_MODULE_GENERAL should be used by modules that do not
# care if return code values overlap. Callers of methods that
@@ -1179,6 +1180,27 @@ with modules["ERRORRESULT"]:
errors["NS_ERROR_INTERNAL_ERRORRESULT_RANGEERROR"] = FAILURE(5)
+# =======================================================================
+# 44: Tor-specific error codes.
+# =======================================================================
+with modules["TOR"]:
+ # Tor onion service descriptor can not be found.
+ errors["NS_ERROR_TOR_ONION_SVC_NOT_FOUND"] = FAILURE(1)
+ # Tor onion service descriptor is invalid.
+ errors["NS_ERROR_TOR_ONION_SVC_IS_INVALID"] = FAILURE(2)
+ # Tor onion service introduction failed.
+ errors["NS_ERROR_TOR_ONION_SVC_INTRO_FAILED"] = FAILURE(3)
+ # Tor onion service rendezvous failed.
+ errors["NS_ERROR_TOR_ONION_SVC_REND_FAILED"] = FAILURE(4)
+ # Tor onion service missing client authorization.
+ errors["NS_ERROR_TOR_ONION_SVC_MISSING_CLIENT_AUTH"] = FAILURE(5)
+ # Tor onion service wrong client authorization.
+ errors["NS_ERROR_TOR_ONION_SVC_BAD_CLIENT_AUTH"] = FAILURE(6)
+ # Tor onion service bad address.
+ errors["NS_ERROR_TOR_ONION_SVC_BAD_ADDRESS"] = FAILURE(7)
+ # Tor onion service introduction timed out.
+ errors["NS_ERROR_TOR_ONION_SVC_INTRO_TIMEDOUT"] = FAILURE(8)
+
# =======================================================================
# 51: NS_ERROR_MODULE_GENERAL
# =======================================================================
1
0

[translation/tpo-web] https://gitweb.torproject.org/translation.git/commit/?h=tpo-web
by translation@torproject.org 17 Mar '21
by translation@torproject.org 17 Mar '21
17 Mar '21
commit 0806c248315243b38b7e195e5e56d1f46c537f10
Author: Translation commit bot <translation(a)torproject.org>
Date: Wed Mar 17 19:17:40 2021 +0000
https://gitweb.torproject.org/translation.git/commit/?h=tpo-web
---
contents+es.po | 144 ++++++++++++++++++++++++++++++++++++++++-----------------
1 file changed, 101 insertions(+), 43 deletions(-)
diff --git a/contents+es.po b/contents+es.po
index 9cebfba780..9a6ac315c9 100644
--- a/contents+es.po
+++ b/contents+es.po
@@ -268,7 +268,7 @@ msgid ""
" services."
msgstr ""
"## Esta nueva versión del Navegador Tor está enfocada en ayudar a los "
-"usuarios a entender los servicios onion."
+"usuarios a entender los servicios cebolla."
#: https//www.torproject.org/releases/tor-browser-95/
#: (content/releases/tor-browser-95/contents+en.lrpage.body)
@@ -283,12 +283,12 @@ msgid ""
msgstr ""
"El enrutamiento tipo cebolla de Tor aún es la mejor manera de lograr una "
"comunicación anónima de extremo a extremo sobre Internet. Con los servicios "
-"onion (direcciones .onion), los administradores de sitios web pueden proveer"
-" a sus usuarios con conexiones anónimas que están libres de metadatos, o que"
-" los esconden de cualquier tercero. Los servicios onion también son una de "
-"las pocas tecnologías de evasión de la censura que permiten a los usuarios "
-"una ruta alternativa alrededor de la misma, mientras que simultáneamente "
-"protegen su privacidad e identidad."
+"cebolla (direcciones .onion), los administradores de sitios web pueden "
+"proveer a sus usuarios con conexiones anónimas que están libres de "
+"metadatos, o que los esconden de cualquier tercero. Los servicios cebolla "
+"también son una de las pocas tecnologías de evasión de la censura que "
+"permiten a los usuarios una ruta alternativa alrededor de la misma, mientras"
+" que simultáneamente protegen su privacidad e identidad."
#: https//www.torproject.org/releases/tor-browser-95/
#: (content/releases/tor-browser-95/contents+en.lrpage.body)
@@ -301,12 +301,12 @@ msgid ""
"invite them to opt-in to use their .onion address."
msgstr ""
"Por primera vez, los usuarios del Navegador Tor podrán optar por el uso de "
-"sitios onion automáticamente en la medida en que el sitio web los haga "
-"disponibles. Por años, algunos sitios web han usado servicios onion en forma"
-" invisible con servicios alternativos, y esto continúa siendo una elección "
-"excelente. Ahora, también hay una opción para sitios web que quieren que sus"
-" usuarios sepan acerca de su servicio onion, para invitarlos a optar por el"
-" uso de su dirección .onion."
+"sitios cebolla automáticamente en la medida en que el sitio web los haga "
+"disponibles. Por años, algunos sitios web han usado servicios cebolla en "
+"forma invisible con servicios alternativos, y esto continúa siendo una "
+"elección excelente. Ahora, también hay una opción para sitios web que "
+"quieren que sus usuarios sepan acerca de su servicio cebolla, para "
+"invitarlos a optar por el uso de su dirección .onion."
#: https//www.torproject.org/releases/tor-browser-95/
#: (content/releases/tor-browser-95/contents+en.lrpage.body)
@@ -327,12 +327,12 @@ msgid ""
"about the onion service version of the site and will be asked to opt-in to "
"upgrade to the onion service on their first use."
msgstr ""
-"Ahora, quienes publican sitios web pueden divulgar su servicio onion a "
+"Ahora, quienes publican sitios web pueden divulgar su servicio cebolla a "
"usuarios de Tor añadiendo un encabezado HTTP. Al visitar un sitio web que "
"tiene tanto una dirección .onion como Onion Location habilitada vía el "
"Navegador Tor, a los usuarios les será notificado acerca de la versión en "
-"servicio onion del sitio, y se les solicitará optar por la actualización a "
-"ese servicio onion en su primer uso."
+"servicio cebolla del sitio, y se les solicitará optar por la actualización a"
+" ese servicio cebolla en su primer uso."
#: https//www.torproject.org/releases/tor-browser-95/
#: (content/releases/tor-browser-95/contents+en.lrpage.body)
@@ -355,7 +355,7 @@ msgid ""
"service.](https://community.torproject.org/onion-services/advanced/onion-"
"location/)"
msgstr ""
-"Si sos un desarrollador, aprendé [cómo habilitar onion-location en tu "
+"Si eres un desarrollador, aprende [cómo habilitar onion-location en tu "
"servicio onion.](https://community.torproject.org/onion-services/advanced"
"/onion-location/)"
@@ -371,8 +371,8 @@ msgid ""
"their website can now set a pair of keys for access control and "
"authentication."
msgstr ""
-"Los administradores de servicios onion que quieren agregar una capa extra de"
-" seguridad a su sitio web, ahora pueden establecer un par de claves para "
+"Los administradores de servicios cebolla que quieren agregar una capa extra "
+"de seguridad a su sitio web, ahora pueden establecer un par de claves para "
"control de acceso y autenticación."
#: https//www.torproject.org/releases/tor-browser-95/
@@ -391,7 +391,7 @@ msgid ""
"about:preferences#privacy in the Onion Services Authentication section."
msgstr ""
"Los usuarios del Navegador Tor pueden guardar sus claves y gestionarlas vía "
-"about:preferences#privacy en la sección Autenticación de Servicios Onion."
+"about:preferences#privacy en la sección Autenticación de Servicios Cebolla."
#: https//www.torproject.org/releases/tor-browser-95/
#: (content/releases/tor-browser-95/contents+en.lrpage.body)
@@ -409,7 +409,7 @@ msgid ""
" auth.](https://community.torproject.org/onion-services/advanced/client-"
"auth/)"
msgstr ""
-"Si sos un desarrollador, aprendé [cómo asegurar tu servicio onion usando "
+"Si eres un desarrollador, aprende [cómo asegurar tu servicio onion usando "
"autorización de cliente.](https://community.torproject.org/onion-"
"services/advanced/client-auth/)"
@@ -432,8 +432,8 @@ msgid ""
"when they are visiting an non-secure website."
msgstr ""
"Tradicionalmente, los navegadores presentaban los sitios entregados a través"
-" de un protocolo de transporte seguro con un icono de un candado verde. Pero"
-" a mediados de 2019, el icono del candado que había sido verde se tornó "
+" de un protocolo de transporte seguro con un ícono de un candado verde. Pero"
+" a mediados de 2019, el ícono del candado que había sido verde se tornó "
"gris, con la intención de quitarle énfasis al estado de conexión por defecto"
" (seguro), y en vez poner un mayor énfasis en conexiones comprometidas o "
"inseguras. Los navegadores principales como Firefox y Chrome entendieron que"
@@ -455,7 +455,7 @@ msgstr ""
#: https//www.torproject.org/releases/tor-browser-95/
#: (content/releases/tor-browser-95/contents+en.lrpage.body)
msgid "**Error pages for onion services**"
-msgstr "**Páginas de error para servicios onion**"
+msgstr "**Páginas de error para servicios cebolla**"
#: https//www.torproject.org/releases/tor-browser-95/
#: (content/releases/tor-browser-95/contents+en.lrpage.body)
@@ -465,11 +465,11 @@ msgid ""
"users received a standard Firefox error message, with no information about "
"why they were unable to connect to the onion site."
msgstr ""
-"A veces, los usuarios tienen grandes dificultades alcanzando sitios onion. "
-"En versiones previas del Navegador Tor, cuando había un error conectándose a"
-" un servicio onion, los usuarios recibían un mensaje de error estándar de "
-"Firefox, sin información acerca de por qué no fueron capaces de conectarse "
-"al sitio onion."
+"A veces, los usuarios tienen grandes dificultades alcanzando sitios cebolla."
+" En versiones previas del Navegador Tor, cuando había un error conectándose "
+"a un servicio cebolla, los usuarios recibían un mensaje de error estándar de"
+" Firefox, sin información acerca de por qué no fueron capaces de conectarse "
+"al sitio cebolla."
#: https//www.torproject.org/releases/tor-browser-95/
#: (content/releases/tor-browser-95/contents+en.lrpage.body)
@@ -480,6 +480,12 @@ msgid ""
"simplified diagram of the connection and shows where the error occured. We "
"want these messages to be clear and informative without being overwhelming."
msgstr ""
+"En esta versión, hemos mejorado la manera en que el Navegador Tor se "
+"comunica con los usuarios acerca de errores en los lados de servicio, "
+"cliente y red, que pueden ocurrir cuando están intentando visitar un "
+"servicio cebolla. El Navegador Tor ahora muestra un diagrama simplificado de"
+" la conexión, indicando dónde ocurrió el error. Queremos que estos mensajes "
+"sean claros e informativos, sin ser abrumadores."
#: https//www.torproject.org/releases/tor-browser-95/
#: (content/releases/tor-browser-95/contents+en.lrpage.body)
@@ -487,11 +493,13 @@ msgid ""
"<img class=\"w-100\" src=\"/static/images/tb95/onion-error(a)2x.png\" "
"alt=\"Tor Browser 9.5 Error Pages for Onionsites\"/>"
msgstr ""
+"<img class=\"w-100\" src=\"/static/images/tb95/onion-error(a)2x.png\" "
+"alt=\"Tor Browser 9.5 Error Pages for Onionsites\"/>"
#: https//www.torproject.org/releases/tor-browser-95/
#: (content/releases/tor-browser-95/contents+en.lrpage.body)
msgid "**Onion Names**"
-msgstr ""
+msgstr "**Nombres Onion**"
#: https//www.torproject.org/releases/tor-browser-95/
#: (content/releases/tor-browser-95/contents+en.lrpage.body)
@@ -508,11 +516,23 @@ msgid ""
"proof-of-concept human-memorable names for SecureDrop onion services "
"addresses:"
msgstr ""
+"Debido a las protecciones criptográficas, los URLs de servicios cebolla no "
+"son fáciles de recordar para seres humanos (ej.: https://torproject.org vs. "
+"http://expyuzz4wqqyqhjn.onion/) Esto hace dificultoso para los usuarios "
+"descubrir o regresar a un sitio cebolla. Nos hemos encontrado con que, "
+"orgánicamente, los desarrolladores han abordado este problema de maneras "
+"diferentes, mayormente con soluciones hechas a la medida para su servicio. "
+"Dado que no hay una solución que funcione perfectamente para todos nuestros "
+"grupos de usuarios, también abordamos este problema desde un ángulo amplio. "
+"Para esta versión, nos asociamos con la Freedom of the Press Foundation "
+"(FPF) y HTTPS Everywhere de la Electronic Frontier Foundation, para "
+"desarrollar los primeros nombres recordables por seres humanos como prueba "
+"de cocepto, para las direcciones de servicios cebolla para SecureDrop:"
#: https//www.torproject.org/releases/tor-browser-95/
#: (content/releases/tor-browser-95/contents+en.lrpage.body)
msgid "The Intercept:"
-msgstr ""
+msgstr "The Intercept:"
#: https//www.torproject.org/releases/tor-browser-95/
#: (content/releases/tor-browser-95/contents+en.lrpage.body)
@@ -527,7 +547,7 @@ msgstr "http://xpxduj55x2j27l2qytu2tcetykyfxbjbafin3x4i3ywddzphkbrd3jyd.onion"
#: https//www.torproject.org/releases/tor-browser-95/
#: (content/releases/tor-browser-95/contents+en.lrpage.body)
msgid "Lucy Parsons Labs:"
-msgstr ""
+msgstr "Lucy Parsons Labs:"
#: https//www.torproject.org/releases/tor-browser-95/
#: (content/releases/tor-browser-95/contents+en.lrpage.body)
@@ -547,6 +567,10 @@ msgid ""
"jointly consider next steps based on feedback on this initial proof-of-"
"concept."
msgstr ""
+"La Freedom of the Press Foundation ha intentado contactar para su "
+"participación a un número reducido de organizaciones mediáticas adicionales,"
+" y en conjunto con Tor, va a considerar los próximos pasos, basados en las "
+"sugerencias sobre esta prueba de concepto inicial."
#: https//www.torproject.org/releases/tor-browser-95/
#: (content/releases/tor-browser-95/contents+en.lrpage.body)
@@ -554,6 +578,8 @@ msgid ""
"<img class=\"w-100\" src=\"/static/images/tb95/onion-names(a)2x.png\" "
"alt=\"Tor Browser 9.5 Onion Names\"/>"
msgstr ""
+"<img class=\"w-100\" src=\"/static/images/tb95/onion-names(a)2x.png\" "
+"alt=\"Tor Browser 9.5 Onion Names\"/>"
#: https//www.torproject.org/releases/tor-browser-95/
#: (content/releases/tor-browser-95/contents+en.lrpage.body)
@@ -569,16 +595,19 @@ msgid ""
"release, please let us know. Thanks to all of the teams across Tor, and the "
"many volunteers, who contributed to this release."
msgstr ""
+"Si encuentras un error o tienes una sugerencia sobre cómo podríamos mejorar "
+"esta versión, por favor haznos saber. Gracias a todos los equipos a lo largo"
+" de Tor, y los muchos voluntarios que contribuyeron a esta versión."
#: https//www.torproject.org/releases/tor-browser-10-0/
#: (content/releases/tor-browser-10-0/contents+en.lrpage.title)
msgid "Tor Browser 10"
-msgstr ""
+msgstr "Navegador Tor 10"
#: https//www.torproject.org/releases/tor-browser-10-0/
#: (content/releases/tor-browser-10-0/contents+en.lrpage.body)
msgid "## New Release: Tor Browser 10"
-msgstr ""
+msgstr "## Nueva Versión: Navegador Tor 10"
#: https//www.torproject.org/releases/tor-browser-10-0/
#: (content/releases/tor-browser-10-0/contents+en.lrpage.body)
@@ -586,6 +615,9 @@ msgid ""
"The new shiny Tor Browser 10 for Desktop is now available from the Tor "
"Browser download page and also from our distribution directory!"
msgstr ""
+"¡El nuevo y radiante Navegador Tor 10 para Escritorio ahora está disponible "
+"desde la página de descarga del Navegador Tor, y también desde nuestro "
+"directorio de distribución!"
#: https//www.torproject.org/releases/tor-browser-10-0/
#: (content/releases/tor-browser-10-0/contents+en.lrpage.body)
@@ -596,6 +628,11 @@ msgid ""
"We expect to release the new Tor Browser for Android based on Fenix in the "
"following weeks."
msgstr ""
+"La versión de Android para el Navegador Tor 10 está bajo desarrollo activo, "
+"y estamos soportando la versión actual hasta que la nueva esté lista. "
+"Mozilla nos informa de cualquier dificultad sobre la que toman conocimiento "
+"que afecte a esta versión. Esperamos lanzar el nuevo Navegador Tor para "
+"Android basado en Fenix en las siguientes semanas."
#: https//www.torproject.org/releases/tor-browser-10-0/
#: (content/releases/tor-browser-10-0/contents+en.lrpage.body)
@@ -604,6 +641,10 @@ msgid ""
"and Tor to 0.4.4.5. This release includes important [security updates to "
"Firefox](https://www.mozilla.org/en-US/security/advisories/mfsa2020-43/)."
msgstr ""
+"El Navegador Tor 10 viene con Firefox 78.3.0esr, actualiza NoScript a "
+"11.0.44, y Tor a 0.4.4.5. Esta versión incluye importantes [actualizaciones "
+"de seguridad para Firefox](https://www.mozilla.org/en-"
+"US/security/advisories/mfsa2020-43/)."
#: https//www.torproject.org/releases/tor-browser-10-0/
#: (content/releases/tor-browser-10-0/contents+en.lrpage.body)
@@ -613,6 +654,10 @@ msgid ""
"US/firefox/enterprise/#overview) of Mozilla Firefox. Tor Browser 10.0 is the"
" first stable release of the 10.0 series based on Firefox 78esr."
msgstr ""
+"Esta nueva versión del Navegador Tor está enfocada en estabilizarlo, "
+"basádose en una [nueva versión de soporte extendido](https://www.mozilla.org"
+"/en-US/firefox/enterprise/#overview) del Mozilla Firefox. El Navegador Tor "
+"10.0 es la primera versión estable de la serie 10.0 basada en Firefox 78esr."
#: https//www.torproject.org/releases/tor-browser-10-0/
#: (content/releases/tor-browser-10-0/contents+en.lrpage.body)
@@ -622,6 +667,10 @@ msgid ""
"browser/-/issues/40089) supporting CentOS 6. Beginning with the 10.5 series,"
" CentOS 6 is not supported."
msgstr ""
+"**Nota:** El Navegador Tor 10.0 es la [serie "
+"final](https://gitlab.torproject.org/tpo/applications/tor-"
+"browser/-/issues/40089) con soporte para CentOS 6. Empezando con la serie "
+"10.5, CentOS 6 no va a ser soportado."
#: https//www.torproject.org/releases/tor-browser-10-0/
#: (content/releases/tor-browser-10-0/contents+en.lrpage.body)
@@ -631,6 +680,10 @@ msgid ""
"feedback/). Thanks to all of the teams across Tor, and the many volunteers, "
"who contributed to this release."
msgstr ""
+"Si encuentras un error o tienes una sugerencia sobre cómo podríamos mejorar "
+"esta versión, [por favor haznos saber](https://support.torproject.org/misc"
+"/bug-or-feedback/). Gracias a todos los equipos a lo largo de Tor, y los "
+"muchos voluntarios que contribuyeron a esta versión."
#: https//www.torproject.org/about/cy-pres/
#: (content/about/cy-pres/contents+en.lrpage.title)
@@ -1099,7 +1152,7 @@ msgstr ""
#: https//www.torproject.org/about/membership/
#: (content/about/membership/contents+en.lrpage.title)
msgid "Membership"
-msgstr ""
+msgstr "Membresía"
#: https//www.torproject.org/about/membership/
#: (content/about/membership/contents+en.lrpage.body)
@@ -1109,6 +1162,11 @@ msgid ""
"supportive relationship between our nonprofit and private sector "
"organizations that use our technology or want to support our mission."
msgstr ""
+"La comunidad siempre ha estado en el corazón de la fortaleza de Tor. En este"
+" espíritu, creamos el Programa de Membresía del Tor Project. Nuestro "
+"objetivo es construir una relación de soporte entre nuestras organizaciones "
+"sin fines de lucro y del sector privado que usen nuestra tecnología o "
+"quieran soportar nuestra misión."
#: https//www.torproject.org/press/-new-release-tails/
#: (content/press/new-release-tails/contents+en.lrpost.title)
@@ -1857,7 +1915,7 @@ msgstr "Te invitamos a unírtenos en IRC para saber cómo puedes involucrarte."
#: templates/membership.html:111
msgid "Green Onion Members"
-msgstr ""
+msgstr "Miembros Green Onion"
#: templates/meta.html:11
msgid "The Tor Project | Privacy & Freedom Online"
@@ -1944,23 +2002,23 @@ msgstr "Tema"
#: templates/privchat-1.html:19 templates/privchat-2.html:19
msgid "Watch"
-msgstr ""
+msgstr "Observa"
#: templates/privchat-1.html:43
msgid "Roger Dingledine"
-msgstr ""
+msgstr "Roger Dingledine"
#: templates/privchat-1.html:62
msgid "Carmela Troncoso"
-msgstr ""
+msgstr "Carmela Troncoso"
#: templates/privchat-1.html:74
msgid "Daniel Kahn Gillmor"
-msgstr ""
+msgstr "Daniel Kahn Gillmor"
#: templates/privchat-1.html:86
msgid "Matt Mitchell "
-msgstr ""
+msgstr "Matt Mitchell "
#: templates/privchat.html:29
msgid "Save the Date"
@@ -1968,7 +2026,7 @@ msgstr ""
#: templates/release.html:22
msgid "Do you need help?"
-msgstr ""
+msgstr "¿Necesitas ayuda?"
#: templates/release.html:31
msgid "Get in Touch"
@@ -2081,7 +2139,7 @@ msgstr "Manual del Tor Browser"
#: templates/macros/downloads.html:72
msgid "blog post"
-msgstr ""
+msgstr "posteo de blog"
#: templates/macros/jobs.html:11
msgid "Read more."
1
0

[translation/tpo-web] https://gitweb.torproject.org/translation.git/commit/?h=tpo-web
by translation@torproject.org 17 Mar '21
by translation@torproject.org 17 Mar '21
17 Mar '21
commit f2c5adfd0a746f477ecde0239010759004b9b0bf
Author: Translation commit bot <translation(a)torproject.org>
Date: Wed Mar 17 18:47:58 2021 +0000
https://gitweb.torproject.org/translation.git/commit/?h=tpo-web
---
contents+el.po | 7 +++---
contents+es.po | 72 ++++++++++++++++++++++++++++++++++++++++++++++++++++------
2 files changed, 69 insertions(+), 10 deletions(-)
diff --git a/contents+el.po b/contents+el.po
index 418360a895..7256d28e30 100644
--- a/contents+el.po
+++ b/contents+el.po
@@ -15,6 +15,7 @@
# Gus, 2020
# Elektra M. <safiragon(a)yahoo.gr>, 2021
# George Kitsoukakis <norhorn(a)gmail.com>, 2021
+# LOUKAS SKOUROLIAKOS, 2021
#
msgid ""
msgstr ""
@@ -22,7 +23,7 @@ msgstr ""
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2021-03-01 14:59+CET\n"
"PO-Revision-Date: 2019-03-09 10:41+0000\n"
-"Last-Translator: George Kitsoukakis <norhorn(a)gmail.com>, 2021\n"
+"Last-Translator: LOUKAS SKOUROLIAKOS, 2021\n"
"Language-Team: Greek (https://www.transifex.com/otf/teams/1519/el/)\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
@@ -167,7 +168,7 @@ msgstr "Κοινότητα"
#: https//www.torproject.org/releases/
#: (content/releases/contents+en.lrpage.title)
msgid "Releases"
-msgstr ""
+msgstr "Εκδόσεις"
#: https//www.torproject.org/releases/
#: (content/releases/contents+en.lrpage.section)
@@ -176,7 +177,7 @@ msgstr ""
#: https//www.torproject.org/releases/tor-browser-10-0/
#: (content/releases/tor-browser-10-0/contents+en.lrpage.section)
msgid "What is new"
-msgstr ""
+msgstr "Τι καινούριο υπάρχει"
#: https//www.torproject.org/thank-you/
#: (content/thank-you/contents+en.lrpage.title)
diff --git a/contents+es.po b/contents+es.po
index 34b921c1ca..9cebfba780 100644
--- a/contents+es.po
+++ b/contents+es.po
@@ -11,9 +11,9 @@
# Gus, 2020
# walking <walking(a)i2pmail.org>, 2021
# erinm, 2021
-# Zuhualime Akoochimoya, 2021
# David Figuera <dfb(a)fastmail.com>, 2021
# Emma Peel, 2021
+# Zuhualime Akoochimoya, 2021
#
msgid ""
msgstr ""
@@ -21,7 +21,7 @@ msgstr ""
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2021-03-01 14:59+CET\n"
"PO-Revision-Date: 2019-03-09 10:41+0000\n"
-"Last-Translator: Emma Peel, 2021\n"
+"Last-Translator: Zuhualime Akoochimoya, 2021\n"
"Language-Team: Spanish (https://www.transifex.com/otf/teams/1519/es/)\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
@@ -267,6 +267,8 @@ msgid ""
"## This new Tor Browser release is focused on helping users understand onion"
" services."
msgstr ""
+"## Esta nueva versión del Navegador Tor está enfocada en ayudar a los "
+"usuarios a entender los servicios onion."
#: https//www.torproject.org/releases/tor-browser-95/
#: (content/releases/tor-browser-95/contents+en.lrpage.body)
@@ -279,6 +281,14 @@ msgid ""
"allow users to route around censorship while simultaneously protecting their"
" privacy and identity."
msgstr ""
+"El enrutamiento tipo cebolla de Tor aún es la mejor manera de lograr una "
+"comunicación anónima de extremo a extremo sobre Internet. Con los servicios "
+"onion (direcciones .onion), los administradores de sitios web pueden proveer"
+" a sus usuarios con conexiones anónimas que están libres de metadatos, o que"
+" los esconden de cualquier tercero. Los servicios onion también son una de "
+"las pocas tecnologías de evasión de la censura que permiten a los usuarios "
+"una ruta alternativa alrededor de la misma, mientras que simultáneamente "
+"protegen su privacidad e identidad."
#: https//www.torproject.org/releases/tor-browser-95/
#: (content/releases/tor-browser-95/contents+en.lrpage.body)
@@ -290,16 +300,23 @@ msgid ""
"for websites that want their users to know about their onion service to "
"invite them to opt-in to use their .onion address."
msgstr ""
+"Por primera vez, los usuarios del Navegador Tor podrán optar por el uso de "
+"sitios onion automáticamente en la medida en que el sitio web los haga "
+"disponibles. Por años, algunos sitios web han usado servicios onion en forma"
+" invisible con servicios alternativos, y esto continúa siendo una elección "
+"excelente. Ahora, también hay una opción para sitios web que quieren que sus"
+" usuarios sepan acerca de su servicio onion, para invitarlos a optar por el"
+" uso de su dirección .onion."
#: https//www.torproject.org/releases/tor-browser-95/
#: (content/releases/tor-browser-95/contents+en.lrpage.body)
msgid "### What is new?"
-msgstr ""
+msgstr "### ¿Qué hay de nuevo?"
#: https//www.torproject.org/releases/tor-browser-95/
#: (content/releases/tor-browser-95/contents+en.lrpage.body)
msgid "**Onion Location**"
-msgstr ""
+msgstr "**Onion Location**"
#: https//www.torproject.org/releases/tor-browser-95/
#: (content/releases/tor-browser-95/contents+en.lrpage.body)
@@ -310,6 +327,12 @@ msgid ""
"about the onion service version of the site and will be asked to opt-in to "
"upgrade to the onion service on their first use."
msgstr ""
+"Ahora, quienes publican sitios web pueden divulgar su servicio onion a "
+"usuarios de Tor añadiendo un encabezado HTTP. Al visitar un sitio web que "
+"tiene tanto una dirección .onion como Onion Location habilitada vía el "
+"Navegador Tor, a los usuarios les será notificado acerca de la versión en "
+"servicio onion del sitio, y se les solicitará optar por la actualización a "
+"ese servicio onion en su primer uso."
#: https//www.torproject.org/releases/tor-browser-95/
#: (content/releases/tor-browser-95/contents+en.lrpage.body)
@@ -317,6 +340,8 @@ msgid ""
"<img class=\"w-100\" src=\"/static/images/tb95/onion-location-"
"propublica(a)2x.png\" alt=\"Tor Browser 9.5 Onion Location\"/>"
msgstr ""
+"<img class=\"w-100\" src=\"/static/images/tb95/onion-location-"
+"propublica(a)2x.png\" alt=\"Tor Browser 9.5 Onion Location\"/>"
#: https//www.torproject.org/releases/tor-browser-95/
#: (content/releases/tor-browser-95/contents+en.lrpage.body)
@@ -330,11 +355,14 @@ msgid ""
"service.](https://community.torproject.org/onion-services/advanced/onion-"
"location/)"
msgstr ""
+"Si sos un desarrollador, aprendé [cómo habilitar onion-location en tu "
+"servicio onion.](https://community.torproject.org/onion-services/advanced"
+"/onion-location/)"
#: https//www.torproject.org/releases/tor-browser-95/
#: (content/releases/tor-browser-95/contents+en.lrpage.body)
msgid "**Onion Authentication**"
-msgstr ""
+msgstr "**Autenticación Onion**"
#: https//www.torproject.org/releases/tor-browser-95/
#: (content/releases/tor-browser-95/contents+en.lrpage.body)
@@ -343,6 +371,9 @@ msgid ""
"their website can now set a pair of keys for access control and "
"authentication."
msgstr ""
+"Los administradores de servicios onion que quieren agregar una capa extra de"
+" seguridad a su sitio web, ahora pueden establecer un par de claves para "
+"control de acceso y autenticación."
#: https//www.torproject.org/releases/tor-browser-95/
#: (content/releases/tor-browser-95/contents+en.lrpage.body)
@@ -350,6 +381,8 @@ msgid ""
"<img class=\"w-100\" src=\"/static/images/tb95/onion-auth(a)2x.png\" alt=\"Tor"
" Browser 9.5 Onion Authentication\"/>"
msgstr ""
+"<img class=\"w-100\" src=\"/static/images/tb95/onion-auth(a)2x.png\" alt=\"Tor"
+" Browser 9.5 Onion Authentication\"/>"
#: https//www.torproject.org/releases/tor-browser-95/
#: (content/releases/tor-browser-95/contents+en.lrpage.body)
@@ -357,6 +390,8 @@ msgid ""
"Tor Browser users can save keys and manage them via "
"about:preferences#privacy in the Onion Services Authentication section."
msgstr ""
+"Los usuarios del Navegador Tor pueden guardar sus claves y gestionarlas vía "
+"about:preferences#privacy en la sección Autenticación de Servicios Onion."
#: https//www.torproject.org/releases/tor-browser-95/
#: (content/releases/tor-browser-95/contents+en.lrpage.body)
@@ -364,6 +399,8 @@ msgid ""
"<img class=\"w-100\" src=\"/static/images/tb95/onion-auth2(a)2x.png\" "
"alt=\"Tor Browser 9.5 Onion Authentication\"/>"
msgstr ""
+"<img class=\"w-100\" src=\"/static/images/tb95/onion-auth2(a)2x.png\" "
+"alt=\"Tor Browser 9.5 Onion Authentication\"/>"
#: https//www.torproject.org/releases/tor-browser-95/
#: (content/releases/tor-browser-95/contents+en.lrpage.body)
@@ -372,11 +409,14 @@ msgid ""
" auth.](https://community.torproject.org/onion-services/advanced/client-"
"auth/)"
msgstr ""
+"Si sos un desarrollador, aprendé [cómo asegurar tu servicio onion usando "
+"autorización de cliente.](https://community.torproject.org/onion-"
+"services/advanced/client-auth/)"
#: https//www.torproject.org/releases/tor-browser-95/
#: (content/releases/tor-browser-95/contents+en.lrpage.body)
msgid "**Improved URL Bar Security Indicators**"
-msgstr ""
+msgstr "**Indicadores de Seguridad Mejorados en la Barra URL**"
#: https//www.torproject.org/releases/tor-browser-95/
#: (content/releases/tor-browser-95/contents+en.lrpage.body)
@@ -391,6 +431,17 @@ msgid ""
"Tor Browser security indicators to make it easier for users to understand "
"when they are visiting an non-secure website."
msgstr ""
+"Tradicionalmente, los navegadores presentaban los sitios entregados a través"
+" de un protocolo de transporte seguro con un icono de un candado verde. Pero"
+" a mediados de 2019, el icono del candado que había sido verde se tornó "
+"gris, con la intención de quitarle énfasis al estado de conexión por defecto"
+" (seguro), y en vez poner un mayor énfasis en conexiones comprometidas o "
+"inseguras. Los navegadores principales como Firefox y Chrome entendieron que"
+" esto es un beneficio para la base de usuarios en su totalidad, si "
+"despliegan experiencias familiares para los usuarios de ambos. Seguimos a "
+"Firefox en esta decisión, y hemos actualizado los indicadores de seguridad "
+"del Navegador Tor para hacer más fácil para los usuarios entender cuándo "
+"están visitando un sitio web no seguro."
#: https//www.torproject.org/releases/tor-browser-95/
#: (content/releases/tor-browser-95/contents+en.lrpage.body)
@@ -398,11 +449,13 @@ msgid ""
"<img class=\"w-100\" src=\"/static/images/tb95/onion-url-bar-update(a)2x.png\""
" alt=\"Tor Browser 9.5 URL Bar Security Indicators\"/>"
msgstr ""
+"<img class=\"w-100\" src=\"/static/images/tb95/onion-url-bar-update(a)2x.png\""
+" alt=\"Tor Browser 9.5 URL Bar Security Indicators\"/>"
#: https//www.torproject.org/releases/tor-browser-95/
#: (content/releases/tor-browser-95/contents+en.lrpage.body)
msgid "**Error pages for onion services**"
-msgstr ""
+msgstr "**Páginas de error para servicios onion**"
#: https//www.torproject.org/releases/tor-browser-95/
#: (content/releases/tor-browser-95/contents+en.lrpage.body)
@@ -412,6 +465,11 @@ msgid ""
"users received a standard Firefox error message, with no information about "
"why they were unable to connect to the onion site."
msgstr ""
+"A veces, los usuarios tienen grandes dificultades alcanzando sitios onion. "
+"En versiones previas del Navegador Tor, cuando había un error conectándose a"
+" un servicio onion, los usuarios recibían un mensaje de error estándar de "
+"Firefox, sin información acerca de por qué no fueron capaces de conectarse "
+"al sitio onion."
#: https//www.torproject.org/releases/tor-browser-95/
#: (content/releases/tor-browser-95/contents+en.lrpage.body)
1
0

[translation/communitytpo-contentspot] https://gitweb.torproject.org/translation.git/commit/?h=communitytpo-contentspot
by translation@torproject.org 17 Mar '21
by translation@torproject.org 17 Mar '21
17 Mar '21
commit 7a6247985497893e3607109e89a0bff826c052a8
Author: Translation commit bot <translation(a)torproject.org>
Date: Wed Mar 17 17:45:16 2021 +0000
https://gitweb.torproject.org/translation.git/commit/?h=communitytpo-conten…
---
contents+ar.po | 19 +++++++++++++++----
1 file changed, 15 insertions(+), 4 deletions(-)
diff --git a/contents+ar.po b/contents+ar.po
index efcba18a11..8987ca5cc5 100644
--- a/contents+ar.po
+++ b/contents+ar.po
@@ -5236,7 +5236,7 @@ msgstr ""
#: https//community.torproject.org/onion-services/setup/
#: (content/onion-services/setup/contents+en.lrpage.body)
msgid "You will need to put the following two lines in your `torrc` file:"
-msgstr ""
+msgstr "ستحتاج إلى وضع السطرين التاليين في ملف `torrc`:"
#: https//community.torproject.org/onion-services/setup/
#: (content/onion-services/setup/contents+en.lrpage.body)
@@ -5246,7 +5246,7 @@ msgstr "HiddenServiceDir /var/lib/tor/my_website/"
#: https//community.torproject.org/onion-services/setup/
#: (content/onion-services/setup/contents+en.lrpage.body)
msgid "HiddenServicePort 80 127.0.0.1:80"
-msgstr ""
+msgstr "HiddenServicePort 80 127.0.0.1:80"
#: https//community.torproject.org/onion-services/setup/
#: (content/onion-services/setup/contents+en.lrpage.body)
@@ -5276,6 +5276,10 @@ msgid ""
"should be redirected to `127.0.0.1:80` (which is where the web server from "
"step 1 is listening)."
msgstr ""
+"يحدد سطر \"HiddenServicePort\" منفذًا افتراضيًا (أي ، المنفذ الذي سيستخدمه "
+"الأشخاص الذين يزورون خدمة البصل الخاصة بك) ، وفي الحالة المذكورة أعلاه ينص "
+"على أنه يجب إعادة توجيه أي حركة مرور واردة إلى المنفذ 80 من خدمة onion "
+"الخاصة بك إلى 127.0 .0.1: 80` (حيث يستمع خادم الويب من الخطوة 1)."
#: https//community.torproject.org/onion-services/setup/
#: (content/onion-services/setup/contents+en.lrpage.body)
@@ -5283,12 +5287,14 @@ msgid ""
"**Tip:** A good practice to avoid leaking an onion service to a local "
"network is to run onion services over Unix sockets instead of a TCP socket."
msgstr ""
+"** نصيحة: ** من الممارسات الجيدة لتجنب تسريب خدمة onion إلى شبكة محلية تشغيل"
+" خدمات onion عبر مقابس يونكس بدلاً من مقبس TCP."
#: https//community.torproject.org/onion-services/setup/
#: (content/onion-services/setup/contents+en.lrpage.body)
msgid ""
"You will need to edit and put the following two lines in your `torrc` file:"
-msgstr ""
+msgstr "ستحتاج إلى تعديل السطرين التاليين ووضعهما في ملف `torrc`:"
#: https//community.torproject.org/onion-services/setup/
#: (content/onion-services/setup/contents+en.lrpage.body)
@@ -5374,7 +5380,7 @@ msgstr "الآن احفظ torrc وأعد تشغيل Tor."
#: https//community.torproject.org/onion-services/setup/
#: (content/onion-services/setup/contents+en.lrpage.body)
msgid "`$ sudo systemctl restart tor`"
-msgstr ""
+msgstr "`$ sudo systemctl restart tor`"
#: https//community.torproject.org/onion-services/setup/
#: (content/onion-services/setup/contents+en.lrpage.body)
@@ -5391,6 +5397,8 @@ msgid ""
"It will print some warnings or error messages. That should give you an idea "
"of what went wrong."
msgstr ""
+"سيتم طباعة بعض التحذيرات أو رسائل الخطأ. يجب أن يعطيك هذا فكرة عن الخطأ الذي"
+" حدث."
#: https//community.torproject.org/onion-services/setup/
#: (content/onion-services/setup/contents+en.lrpage.body)
@@ -5399,6 +5407,9 @@ msgid ""
"(See the [logging FAQ](https://www.torproject.org/docs/faq#Logs) entry if "
"you don't know how to enable or find your log file.)"
msgstr ""
+"عادة ، هناك أخطاء إملائية في `torrc` أو أذونات دليل خاطئة (راجع إدخال [تسجيل"
+" الدخول] (https://www.torproject.org/docs/faq#Logs) إذا كنت لا تعرف كيفية "
+"التمكين أو العثور على ملف السجل الخاص بك.)"
#: https//community.torproject.org/onion-services/setup/
#: (content/onion-services/setup/contents+en.lrpage.body)
1
0

[translation/communitytpo-contentspot] https://gitweb.torproject.org/translation.git/commit/?h=communitytpo-contentspot
by translation@torproject.org 17 Mar '21
by translation@torproject.org 17 Mar '21
17 Mar '21
commit e9435d2fec3cde535d3e71e75a3f4c81556a777d
Author: Translation commit bot <translation(a)torproject.org>
Date: Wed Mar 17 17:15:12 2021 +0000
https://gitweb.torproject.org/translation.git/commit/?h=communitytpo-conten…
---
contents+ar.po | 10 +++++++---
1 file changed, 7 insertions(+), 3 deletions(-)
diff --git a/contents+ar.po b/contents+ar.po
index 5dc153ad4d..efcba18a11 100644
--- a/contents+ar.po
+++ b/contents+ar.po
@@ -5136,11 +5136,12 @@ msgid ""
"Apache is available in the main repository of multiple Linux and *BSD "
"distributions."
msgstr ""
+"يتوفر اباتشي في المستودع الرئيسي لتوزيعات لينكس و * بي اس دي المتعددة."
#: https//community.torproject.org/onion-services/setup/
#: (content/onion-services/setup/contents+en.lrpage.body)
msgid "To install `apache2` package:"
-msgstr ""
+msgstr "لتثبيت حزمة `اباتشي 2`:"
#: https//community.torproject.org/onion-services/setup/
#: (content/onion-services/setup/contents+en.lrpage.body)
@@ -5160,11 +5161,12 @@ msgid ""
"Nginx is available in the main repository of multiple Linux and *BSD "
"distributions."
msgstr ""
+"يتوفر إنجينكس في المستودع الرئيسي لتوزيعات لينكس و * بي اس دي المتعددة."
#: https//community.torproject.org/onion-services/setup/
#: (content/onion-services/setup/contents+en.lrpage.body)
msgid "To install `nginx` package:"
-msgstr ""
+msgstr "لتثبيت حزمة `إنجينكس`:"
#: https//community.torproject.org/onion-services/setup/
#: (content/onion-services/setup/contents+en.lrpage.body)
@@ -5176,7 +5178,7 @@ msgstr "`$ sudo apt install nginx`"
msgid ""
"By default, the web server will be running on `localhost:80` at the end of "
"the installation."
-msgstr ""
+msgstr "بشكل افتراضي ، سيعمل خادم الويب على `localhost:80` في نهاية التثبيت."
#: https//community.torproject.org/onion-services/setup/
#: (content/onion-services/setup/contents+en.lrpage.body)
@@ -5197,6 +5199,8 @@ msgid ""
"Once your web server is set up, make sure it works: open your browser and go"
" to http://localhost/."
msgstr ""
+"بمجرد إعداد خادم الويب ، تأكد من أنه يعمل: افتح المتصفح وانتقل إلى http: // "
+"localhost /."
#: https//community.torproject.org/onion-services/setup/
#: (content/onion-services/setup/contents+en.lrpage.body)
1
0