tbb-commits
Threads by month
- ----- 2026 -----
- March
- February
- January
- ----- 2025 -----
- December
- November
- October
- September
- August
- 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
- 1 participants
- 20199 discussions
[tor-browser/tor-browser-68.6.0esr-9.5-1] Merge remote-tracking branch 'bradetpo/bug19251-04' into tor-browser-68.6.0esr-9.5-1
by sysrqb@torproject.org 03 Apr '20
by sysrqb@torproject.org 03 Apr '20
03 Apr '20
commit 31200493ae908e01ecbeeb44e0546a354ea8736d
Merge: 7306a08365be e3b4a8bf4a19
Author: Matthew Finkel <sysrqb(a)torproject.org>
Date: Fri Apr 3 02:03:43 2020 +0000
Merge remote-tracking branch 'bradetpo/bug19251-04' into tor-browser-68.6.0esr-9.5-1
browser/actors/NetErrorChild.jsm | 10 +
.../components/onionservices/content/authPrompt.js | 20 +-
.../components/onionservices/content/authUtil.jsm | 16 +-
.../onionservices/content/netError/browser.svg | 3 +
.../onionservices/content/netError/network.svg | 3 +
.../content/netError/onionNetError.css | 65 ++++++
.../content/netError/onionNetError.jsm | 253 +++++++++++++++++++++
.../onionservices/content/netError/onionsite.svg | 7 +
browser/components/onionservices/jar.mn | 1 +
browser/modules/TorStrings.jsm | 48 ++++
docshell/base/nsDocShell.cpp | 47 ++--
dom/ipc/BrowserParent.cpp | 4 +-
dom/ipc/BrowserParent.h | 2 +-
dom/ipc/PBrowser.ipdl | 3 +-
js/xpconnect/src/xpc.msg | 2 +
netwerk/socket/nsSOCKSIOLayer.cpp | 11 +
xpcom/base/ErrorList.py | 4 +
17 files changed, 472 insertions(+), 27 deletions(-)
1
0
[tor-browser/tor-browser-68.6.0esr-9.5-1] Bug 21952: Implement Onion-Location
by sysrqb@torproject.org 03 Apr '20
by sysrqb@torproject.org 03 Apr '20
03 Apr '20
commit da5513527e50e7f13e3b1c3206ed75ff8fbd76db
Author: Alex Catarineu <acat(a)torproject.org>
Date: Thu Mar 5 22:16:39 2020 +0100
Bug 21952: Implement Onion-Location
Whenever a valid Onion-Location HTTP header (or corresponding HTML
<meta> http-equiv attribute) is found in a document load, we either
redirect to it (if the user opted-in via preference) or notify the
presence of an onionsite alternative with a badge in the urlbar.
---
browser/base/content/browser.js | 12 ++
browser/base/content/browser.xul | 3 +
browser/components/BrowserGlue.jsm | 10 ++
.../onionservices/OnionLocationChild.jsm | 43 ++++++
.../onionservices/OnionLocationParent.jsm | 161 +++++++++++++++++++++
.../content/onionlocation-notification-icons.css | 5 +
.../onionservices/content/onionlocation-urlbar.css | 27 ++++
.../content/onionlocation-urlbar.inc.xul | 10 ++
.../onionservices/content/onionlocation.svg | 3 +
.../content/onionlocationPreferences.inc.xul | 11 ++
.../content/onionlocationPreferences.js | 31 ++++
browser/components/onionservices/jar.mn | 2 +
browser/components/onionservices/moz.build | 5 +
.../components/preferences/in-content/privacy.js | 17 +++
.../components/preferences/in-content/privacy.xul | 2 +
browser/modules/TorStrings.jsm | 39 +++++
browser/themes/shared/notification-icons.inc.css | 2 +
browser/themes/shared/urlbar-searchbar.inc.css | 2 +
dom/base/Document.cpp | 32 +++-
dom/base/Document.h | 2 +
dom/webidl/Document.webidl | 9 ++
modules/libpref/init/StaticPrefList.h | 7 +
xpcom/ds/StaticAtoms.py | 1 +
23 files changed, 435 insertions(+), 1 deletion(-)
diff --git a/browser/base/content/browser.js b/browser/base/content/browser.js
index 3f9bf006f562..410c8f62d0ef 100644
--- a/browser/base/content/browser.js
+++ b/browser/base/content/browser.js
@@ -43,6 +43,7 @@ XPCOMUtils.defineLazyModuleGetters(this, {
NetUtil: "resource://gre/modules/NetUtil.jsm",
NewTabUtils: "resource://gre/modules/NewTabUtils.jsm",
OpenInTabsUtils: "resource:///modules/OpenInTabsUtils.jsm",
+ OnionLocationParent: "resource:///modules/OnionLocationParent.jsm",
PageActions: "resource:///modules/PageActions.jsm",
PageThumbs: "resource://gre/modules/PageThumbs.jsm",
PanelMultiView: "resource:///modules/PanelMultiView.jsm",
@@ -5934,6 +5935,7 @@ var XULBrowserWindow = {
Services.obs.notifyObservers(null, "touchbar-location-change", location);
UpdateBackForwardCommands(gBrowser.webNavigation);
ReaderParent.updateReaderButton(gBrowser.selectedBrowser);
+ OnionLocationParent.updateOnionLocationBadge(gBrowser.selectedBrowser);
if (!gMultiProcessBrowser) {
// Bug 1108553 - Cannot rotate images with e10s
@@ -6581,6 +6583,16 @@ var TabsProgressListener = {
},
onStateChange(aBrowser, aWebProgress, aRequest, aStateFlags, aStatus) {
+ // Clear OnionLocation UI
+ if (
+ aStateFlags & Ci.nsIWebProgressListener.STATE_START &&
+ aStateFlags & Ci.nsIWebProgressListener.STATE_IS_NETWORK &&
+ aRequest &&
+ aWebProgress.isTopLevel
+ ) {
+ OnionLocationParent.onStateChange(aBrowser);
+ }
+
// Collect telemetry data about tab load times.
if (
aWebProgress.isTopLevel &&
diff --git a/browser/base/content/browser.xul b/browser/base/content/browser.xul
index d2f72eea8edb..4309a0b71228 100644
--- a/browser/base/content/browser.xul
+++ b/browser/base/content/browser.xul
@@ -992,6 +992,9 @@
onclick="FullZoom.reset();"
tooltip="dynamic-shortcut-tooltip"
hidden="true"/>
+
+#include ../../components/onionservices/content/onionlocation-urlbar.inc.xul
+
<box id="pageActionSeparator" class="urlbar-page-action"/>
<image id="pageActionButton"
class="urlbar-icon urlbar-page-action"
diff --git a/browser/components/BrowserGlue.jsm b/browser/components/BrowserGlue.jsm
index 4e851289fbe9..fd2cbfe1d64f 100644
--- a/browser/components/BrowserGlue.jsm
+++ b/browser/components/BrowserGlue.jsm
@@ -216,6 +216,14 @@ let LEGACY_ACTORS = {
},
},
+ OnionLocation: {
+ child: {
+ module: "resource:///modules/OnionLocationChild.jsm",
+ events: { pageshow: {} },
+ messages: ["OnionLocation:Refresh"],
+ },
+ },
+
PageInfo: {
child: {
module: "resource:///actors/PageInfoChild.jsm",
@@ -507,6 +515,7 @@ XPCOMUtils.defineLazyModuleGetters(this, {
ContentClick: "resource:///modules/ContentClick.jsm",
FormValidationHandler: "resource:///modules/FormValidationHandler.jsm",
LoginManagerParent: "resource://gre/modules/LoginManagerParent.jsm",
+ OnionLocationParent: "resource:///modules/OnionLocationParent.jsm",
PictureInPicture: "resource://gre/modules/PictureInPicture.jsm",
ReaderParent: "resource:///modules/ReaderParent.jsm",
RemotePrompt: "resource:///modules/RemotePrompt.jsm",
@@ -605,6 +614,7 @@ const listeners = {
ContentSearch: ["ContentSearch"],
"FormValidation:ShowPopup": ["FormValidationHandler"],
"FormValidation:HidePopup": ["FormValidationHandler"],
+ "OnionLocation:Set": ["OnionLocationParent"],
"PictureInPicture:Request": ["PictureInPicture"],
"PictureInPicture:Close": ["PictureInPicture"],
"PictureInPicture:Playing": ["PictureInPicture"],
diff --git a/browser/components/onionservices/OnionLocationChild.jsm b/browser/components/onionservices/OnionLocationChild.jsm
new file mode 100644
index 000000000000..1059eb7d5925
--- /dev/null
+++ b/browser/components/onionservices/OnionLocationChild.jsm
@@ -0,0 +1,43 @@
+// Copyright (c) 2020, The Tor Project, Inc.
+
+"use strict";
+
+var EXPORTED_SYMBOLS = ["OnionLocationChild"];
+
+const { ActorChild } = ChromeUtils.import(
+ "resource://gre/modules/ActorChild.jsm"
+);
+
+class OnionLocationChild extends ActorChild {
+ handleEvent(event) {
+ this.onPageShow(event);
+ }
+
+ onPageShow(event) {
+ if (event.target != this.content.document) {
+ return;
+ }
+ const onionLocationURI = this.content.document.onionLocationURI;
+ if (onionLocationURI) {
+ this.mm.sendAsyncMessage("OnionLocation:Set");
+ }
+ }
+
+ receiveMessage(aMessage) {
+ if (aMessage.name == "OnionLocation:Refresh") {
+ const doc = this.content.document;
+ const docShell = this.mm.docShell;
+ const onionLocationURI = doc.onionLocationURI;
+ const refreshURI = docShell.QueryInterface(Ci.nsIRefreshURI);
+ if (onionLocationURI && refreshURI) {
+ refreshURI.refreshURI(
+ onionLocationURI,
+ doc.nodePrincipal,
+ 0,
+ false,
+ true
+ );
+ }
+ }
+ }
+}
diff --git a/browser/components/onionservices/OnionLocationParent.jsm b/browser/components/onionservices/OnionLocationParent.jsm
new file mode 100644
index 000000000000..1c79fc07d215
--- /dev/null
+++ b/browser/components/onionservices/OnionLocationParent.jsm
@@ -0,0 +1,161 @@
+// Copyright (c) 2020, The Tor Project, Inc.
+
+"use strict";
+
+var EXPORTED_SYMBOLS = ["OnionLocationParent"];
+
+const { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm");
+const { TorStrings } = ChromeUtils.import("resource:///modules/TorStrings.jsm");
+
+// Prefs
+const NOTIFICATION_PREF = "privacy.prioritizeonions.showNotification";
+const PRIORITIZE_ONIONS_PREF = "privacy.prioritizeonions.enabled";
+
+// Element IDs
+const ONIONLOCATION_BOX_ID = "onion-location-box";
+const ONIONLOCATION_BUTTON_ID = "onion-location-button";
+const ONIONLOCATION_LABEL_ID = "onion-label";
+
+// Notification IDs
+const NOTIFICATION_ID = "onion-location";
+const NOTIFICATION_ANCHOR_ID = "onionlocation";
+
+// Strings
+const STRING_ONION_AVAILABLE = TorStrings.onionLocation.onionAvailable;
+const NOTIFICATION_CANCEL_LABEL = TorStrings.onionLocation.notNow;
+const NOTIFICATION_CANCEL_ACCESSKEY = TorStrings.onionLocation.notNowAccessKey;
+const NOTIFICATION_OK_LABEL = TorStrings.onionLocation.alwaysPrioritize;
+const NOTIFICATION_OK_ACCESSKEY =
+ TorStrings.onionLocation.alwaysPrioritizeAccessKey;
+const NOTIFICATION_TITLE = TorStrings.onionLocation.tryThis;
+const NOTIFICATION_DESCRIPTION = TorStrings.onionLocation.description;
+const NOTIFICATION_LEARN_MORE_URL = TorStrings.onionLocation.learnMoreURL;
+
+var OnionLocationParent = {
+ // Listeners are added in BrowserGlue.jsm
+ receiveMessage(aMsg) {
+ switch (aMsg.name) {
+ case "OnionLocation:Set":
+ this.setOnionLocation(aMsg.target);
+ break;
+ }
+ },
+
+ buttonClick(event) {
+ if (event.button != 0) {
+ return;
+ }
+ const win = event.target.ownerGlobal;
+ const browser = win.gBrowser.selectedBrowser;
+ this.redirect(browser);
+ },
+
+ redirect(browser) {
+ browser.messageManager.sendAsyncMessage("OnionLocation:Refresh");
+ this.setDisabled(browser);
+ },
+
+ onStateChange(browser) {
+ delete browser._onionLocation;
+ this.hideNotification(browser);
+ },
+
+ setOnionLocation(browser) {
+ const win = browser.ownerGlobal;
+ browser._onionLocation = true;
+ if (browser === win.gBrowser.selectedBrowser) {
+ this.updateOnionLocationBadge(browser);
+ }
+ },
+
+ hideNotification(browser) {
+ const win = browser.ownerGlobal;
+ if (browser._onionLocationPrompt) {
+ win.PopupNotifications.remove(browser._onionLocationPrompt);
+ }
+ },
+
+ showNotification(browser) {
+ const mustShow = Services.prefs.getBoolPref(NOTIFICATION_PREF, true);
+ if (!mustShow) {
+ return;
+ }
+
+ const win = browser.ownerGlobal;
+ Services.prefs.setBoolPref(NOTIFICATION_PREF, false);
+
+ const mainAction = {
+ label: NOTIFICATION_OK_LABEL,
+ accessKey: NOTIFICATION_OK_ACCESSKEY,
+ callback() {
+ Services.prefs.setBoolPref(PRIORITIZE_ONIONS_PREF, true);
+ OnionLocationParent.redirect(browser);
+ win.openPreferences("privacy-onionservices");
+ },
+ };
+
+ const cancelAction = {
+ label: NOTIFICATION_CANCEL_LABEL,
+ accessKey: NOTIFICATION_CANCEL_ACCESSKEY,
+ callback: () => {},
+ };
+
+ const options = {
+ autofocus: true,
+ persistent: true,
+ removeOnDismissal: false,
+ eventCallback(aTopic) {
+ if (aTopic === "removed") {
+ delete browser._onionLocationPrompt;
+ delete browser.onionpopupnotificationanchor;
+ }
+ },
+ learnMoreURL: NOTIFICATION_LEARN_MORE_URL,
+ displayURI: {
+ hostPort: NOTIFICATION_TITLE, // This is hacky, but allows us to have a title without extra markup/css.
+ },
+ hideClose: true,
+ popupIconClass: "onionlocation-notification-icon",
+ };
+
+ // A hacky way of setting the popup anchor outside the usual url bar icon box
+ // onionlocationpopupnotificationanchor comes from `${ANCHOR_ID}popupnotificationanchor`
+ // From https://searchfox.org/mozilla-esr68/rev/080f9ed47742644d2ff84f7aa0b10aea5c4…
+ browser.onionlocationpopupnotificationanchor = win.document.getElementById(
+ ONIONLOCATION_BUTTON_ID
+ );
+
+ browser._onionLocationPrompt = win.PopupNotifications.show(
+ browser,
+ NOTIFICATION_ID,
+ NOTIFICATION_DESCRIPTION,
+ NOTIFICATION_ANCHOR_ID,
+ mainAction,
+ [cancelAction],
+ options
+ );
+ },
+
+ setEnabled(browser) {
+ const win = browser.ownerGlobal;
+ const label = win.document.getElementById(ONIONLOCATION_LABEL_ID);
+ label.textContent = STRING_ONION_AVAILABLE;
+ const elem = win.document.getElementById(ONIONLOCATION_BOX_ID);
+ elem.removeAttribute("hidden");
+ },
+
+ setDisabled(browser) {
+ const win = browser.ownerGlobal;
+ const elem = win.document.getElementById(ONIONLOCATION_BOX_ID);
+ elem.setAttribute("hidden", true);
+ },
+
+ updateOnionLocationBadge(browser) {
+ if (browser._onionLocation) {
+ this.setEnabled(browser);
+ this.showNotification(browser);
+ } else {
+ this.setDisabled(browser);
+ }
+ },
+};
diff --git a/browser/components/onionservices/content/onionlocation-notification-icons.css b/browser/components/onionservices/content/onionlocation-notification-icons.css
new file mode 100644
index 000000000000..7c8a6d892c6f
--- /dev/null
+++ b/browser/components/onionservices/content/onionlocation-notification-icons.css
@@ -0,0 +1,5 @@
+/* Copyright (c) 2020, The Tor Project, Inc. */
+
+.onionlocation-notification-icon {
+ display: none;
+}
\ No newline at end of file
diff --git a/browser/components/onionservices/content/onionlocation-urlbar.css b/browser/components/onionservices/content/onionlocation-urlbar.css
new file mode 100644
index 000000000000..91cad5f178d1
--- /dev/null
+++ b/browser/components/onionservices/content/onionlocation-urlbar.css
@@ -0,0 +1,27 @@
+/* Copyright (c) 2020, The Tor Project, Inc. */
+
+#onion-location-button {
+ list-style-image: url(chrome://browser/content/onionservices/onionlocation.svg);
+}
+
+#onion-location-box {
+ border-radius: 3px;
+ background-color: #6200A4;
+ padding-left: 5px;
+ padding-right: 5px;
+ color: white;
+ -moz-context-properties: fill;
+ fill: white;
+}
+
+#onion-location-box:hover {
+ background-color: #0060DF !important;
+}
+
+toolbar[brighttext] #onion-location-box {
+ background-color: #9400ff;
+}
+
+toolbar[brighttext] #onion-location-box:hover {
+ background-color: #0060DF !important;
+}
diff --git a/browser/components/onionservices/content/onionlocation-urlbar.inc.xul b/browser/components/onionservices/content/onionlocation-urlbar.inc.xul
new file mode 100644
index 000000000000..b612a4236f3c
--- /dev/null
+++ b/browser/components/onionservices/content/onionlocation-urlbar.inc.xul
@@ -0,0 +1,10 @@
+# Copyright (c) 2020, The Tor Project, Inc.
+
+<hbox id="onion-location-box"
+ class="urlbar-icon-wrapper urlbar-page-action"
+ role="button"
+ hidden="true"
+ onclick="OnionLocationParent.buttonClick(event);">
+ <image id="onion-location-button" role="presentation"/>
+ <hbox id="onion-label-container"><label id="onion-label"/></hbox>
+</hbox>
diff --git a/browser/components/onionservices/content/onionlocation.svg b/browser/components/onionservices/content/onionlocation.svg
new file mode 100644
index 000000000000..37f40ac1812f
--- /dev/null
+++ b/browser/components/onionservices/content/onionlocation.svg
@@ -0,0 +1,3 @@
+<svg width="16" height="16" viewBox="0 0 16 16" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+ <path fill="context-fill" fill-opacity="context-fill-opacity" d="m8.016411 14.54499v-0.969784c3.071908-0.0089 5.559239-2.501304 5.559239-5.575429 0-3.073903-2.487331-5.566336-5.559239-5.575206v-0.9697843c3.607473 0.00909 6.528802 2.935521 6.528802 6.544991 0 3.609691-2.921329 6.536342-6.528802 6.545213zm0-3.394356c1.732661-0.0091 3.135111-1.415756 3.135111-3.150857 0-1.734878-1.402451-3.141542-3.135111-3.150634v-0.9695626c2.268448 0.00887 4.104895 1.849753 4.104895 4.120197 0 2.270666-1.836447 4.111549-4.104895 4.120419zm0-4.846926c0.9294227 0.00887 1.680545 0.7644289 1.680545 1.696069 0 0.9318627-0.7511226 1.687421-1.680545 1.696291zm-8.016411 1.696069c0 4.418473 3.581527 8.000222 8 8.000222 4.418251 0 8-3.581749 8-8.000222 0-4.418251-3.581749-7.999778-8-7.999778-4.418473 0-8 3.581527-8 7.999778z" />
+</svg>
\ No newline at end of file
diff --git a/browser/components/onionservices/content/onionlocationPreferences.inc.xul b/browser/components/onionservices/content/onionlocationPreferences.inc.xul
new file mode 100644
index 000000000000..c386316c98dc
--- /dev/null
+++ b/browser/components/onionservices/content/onionlocationPreferences.inc.xul
@@ -0,0 +1,11 @@
+# Copyright (c) 2020, The Tor Project, Inc.
+
+<groupbox id="onionServicesGroup" data-category="panePrivacy" data-subcategory="onionservices">
+ <label><html:h2 id="onionServicesTitle"></html:h2></label>
+ <label><label class="tail-with-learn-more" id="prioritizeOnionsDesc"></label><label
+ class="learnMore" is="text-link" id="onionServicesLearnMore"></label></label>
+ <radiogroup id="prioritizeOnionsRadioGroup" aria-labelledby="prioritizeOnionsDesc" preference="privacy.prioritizeonions.enabled">
+ <radio id="onionServicesRadioAlways" value="true"/>
+ <radio id="onionServicesRadioAsk" value="false"/>
+ </radiogroup>
+</groupbox>
diff --git a/browser/components/onionservices/content/onionlocationPreferences.js b/browser/components/onionservices/content/onionlocationPreferences.js
new file mode 100644
index 000000000000..aa569b54721c
--- /dev/null
+++ b/browser/components/onionservices/content/onionlocationPreferences.js
@@ -0,0 +1,31 @@
+// Copyright (c) 2020, The Tor Project, Inc.
+
+"use strict";
+
+ChromeUtils.defineModuleGetter(
+ this,
+ "TorStrings",
+ "resource:///modules/TorStrings.jsm"
+);
+
+const OnionLocationPreferences = {
+ init() {
+ document.getElementById("onionServicesTitle").textContent =
+ TorStrings.onionLocation.onionServicesTitle;
+ document.getElementById("prioritizeOnionsDesc").textContent =
+ TorStrings.onionLocation.prioritizeOnionsDescription;
+ const learnMore = document.getElementById("onionServicesLearnMore");
+ learnMore.textContent = TorStrings.onionLocation.learnMore;
+ learnMore.href = TorStrings.onionLocation.learnMoreURL;
+ document.getElementById("onionServicesRadioAlways").label =
+ TorStrings.onionLocation.always;
+ document.getElementById("onionServicesRadioAsk").label =
+ TorStrings.onionLocation.askEverytime;
+ },
+};
+
+Object.defineProperty(this, "OnionLocationPreferences", {
+ value: OnionLocationPreferences,
+ enumerable: true,
+ writable: false,
+});
diff --git a/browser/components/onionservices/jar.mn b/browser/components/onionservices/jar.mn
index 583ab77bc6d8..d536e172721c 100644
--- a/browser/components/onionservices/jar.mn
+++ b/browser/components/onionservices/jar.mn
@@ -6,3 +6,5 @@ browser.jar:
content/browser/onionservices/onionservices.css (content/onionservices.css)
content/browser/onionservices/savedKeysDialog.js (content/savedKeysDialog.js)
content/browser/onionservices/savedKeysDialog.xul (content/savedKeysDialog.xul)
+ content/browser/onionservices/onionlocationPreferences.js (content/onionlocationPreferences.js)
+ content/browser/onionservices/onionlocation.svg (content/onionlocation.svg)
diff --git a/browser/components/onionservices/moz.build b/browser/components/onionservices/moz.build
index 7e103239c8d6..bf276c4a3c4c 100644
--- a/browser/components/onionservices/moz.build
+++ b/browser/components/onionservices/moz.build
@@ -1 +1,6 @@
JAR_MANIFESTS += ['jar.mn']
+
+EXTRA_JS_MODULES += [
+ 'OnionLocationChild.jsm',
+ 'OnionLocationParent.jsm',
+]
diff --git a/browser/components/preferences/in-content/privacy.js b/browser/components/preferences/in-content/privacy.js
index ee86b4158d7c..015ee77932b7 100644
--- a/browser/components/preferences/in-content/privacy.js
+++ b/browser/components/preferences/in-content/privacy.js
@@ -75,6 +75,12 @@ XPCOMUtils.defineLazyScriptGetter(
"chrome://browser/content/securitylevel/securityLevel.js"
);
+XPCOMUtils.defineLazyScriptGetter(
+ this,
+ ["OnionLocationPreferences"],
+ "chrome://browser/content/onionservices/onionlocationPreferences.js"
+);
+
XPCOMUtils.defineLazyServiceGetter(
this,
"listManager",
@@ -124,6 +130,9 @@ Preferences.addAll([
// Do not track
{ id: "privacy.donottrackheader.enabled", type: "bool" },
+ // Onion Location
+ { id: "privacy.prioritizeonions.enabled", type: "bool" },
+
// Media
{ id: "media.autoplay.default", type: "int" },
@@ -251,6 +260,13 @@ var gPrivacyPane = {
},
/**
+ * Show the OnionLocation preferences UI
+ */
+ _initOnionLocation() {
+ OnionLocationPreferences.init();
+ },
+
+ /**
* Whether the prompt to restart Firefox should appear when changing the autostart pref.
*/
_shouldPromptForRestart: true,
@@ -377,6 +393,7 @@ var gPrivacyPane = {
this._initTrackingProtectionExtensionControl();
OnionServicesAuthPreferences.init();
this._initSecurityLevel();
+ this._initOnionLocation();
Services.telemetry.setEventRecordingEnabled("pwmgr", true);
diff --git a/browser/components/preferences/in-content/privacy.xul b/browser/components/preferences/in-content/privacy.xul
index e807ac69f1f1..05c4966a1e59 100644
--- a/browser/components/preferences/in-content/privacy.xul
+++ b/browser/components/preferences/in-content/privacy.xul
@@ -15,6 +15,8 @@
<html:h1 data-l10n-id="privacy-header"/>
</hbox>
+#include ../../onionservices/content/onionlocationPreferences.inc.xul
+
<!-- Tracking / Content Blocking -->
<groupbox id="trackingGroup" data-category="panePrivacy" hidden="true" aria-describedby="contentBlockingDescription">
<label id="contentBlockingHeader"><html:h2 data-l10n-id="content-blocking-header"/></label>
diff --git a/browser/modules/TorStrings.jsm b/browser/modules/TorStrings.jsm
index e9a8b3969297..34b13f33a96a 100644
--- a/browser/modules/TorStrings.jsm
+++ b/browser/modules/TorStrings.jsm
@@ -359,6 +359,45 @@ var TorStrings = {
return retval;
})() /* Tor Onion Services Strings */,
+ /*
+ OnionLocation
+ */
+ onionLocation: (function() {
+ const tsb = new TorPropertyStringBundle(
+ ["chrome://torbutton/locale/torbutton.properties"],
+ "onionLocation."
+ );
+ const getString = function(key, fallback) {
+ return tsb.getString(key, fallback);
+ };
+
+ const retval = {
+ alwaysPrioritize: getString(
+ "alwaysPrioritize",
+ "Always Prioritize Onionsites"
+ ),
+ alwaysPrioritizeAccessKey: getString("alwaysPrioritizeAccessKey", "a"),
+ notNow: getString("notNow", "Not Now"),
+ notNowAccessKey: getString("notNowAccessKey", "n"),
+ description: getString(
+ "description",
+ "Website publishers can protect users by adding a security layer. This prevents eavesdroppers from knowing that you are the one visiting that website."
+ ),
+ tryThis: getString("tryThis", "Try this: Onionsite"),
+ onionAvailable: getString("onionAvailable", "Onionsite available"),
+ learnMore: getString("learnMore", "Learn more"),
+ learnMoreURL: `https://tb-manual.torproject.org/${getLocale()}`, // TODO: replace when manual page is available.
+ always: getString("always", "Always"),
+ askEverytime: getString("askEverytime", "Ask you every time"),
+ prioritizeOnionsDescription: getString(
+ "prioritizeOnionsDescription",
+ "Prioritize onionsites when they are available."
+ ),
+ onionServicesTitle: getString("onionServicesTitle", "Onion Services"),
+ };
+
+ return retval;
+ })() /* OnionLocation */,
/*
Tor Deamon Configuration Key Strings
diff --git a/browser/themes/shared/notification-icons.inc.css b/browser/themes/shared/notification-icons.inc.css
index d35f292a0860..afe67decceaf 100644
--- a/browser/themes/shared/notification-icons.inc.css
+++ b/browser/themes/shared/notification-icons.inc.css
@@ -393,3 +393,5 @@ html|*#webRTC-previewVideo {
background: #FFE900 url(chrome://browser/skin/notification-icons/update.svg) no-repeat center;
border-radius: 50%;
}
+
+%include ../../components/onionservices/content/onionlocation-notification-icons.css
\ No newline at end of file
diff --git a/browser/themes/shared/urlbar-searchbar.inc.css b/browser/themes/shared/urlbar-searchbar.inc.css
index a13d402f17e3..40d42921db30 100644
--- a/browser/themes/shared/urlbar-searchbar.inc.css
+++ b/browser/themes/shared/urlbar-searchbar.inc.css
@@ -789,3 +789,5 @@
#urlbar.hidden-focus[focused="true"] {
caret-color: transparent;
}
+
+%include ../../components/onionservices/content/onionlocation-urlbar.css
diff --git a/dom/base/Document.cpp b/dom/base/Document.cpp
index 95b95c9fd69e..994f52659265 100644
--- a/dom/base/Document.cpp
+++ b/dom/base/Document.cpp
@@ -2078,6 +2078,7 @@ void Document::ResetToURI(nsIURI* aURI, nsILoadGroup* aLoadGroup,
// mDocumentURI.
mDocumentBaseURI = nullptr;
mChromeXHRDocBaseURI = nullptr;
+ mOnionLocationURI = nullptr;
if (aLoadGroup) {
mDocumentLoadGroup = do_GetWeakReference(aLoadGroup);
@@ -3731,6 +3732,21 @@ void Document::GetHeaderData(nsAtom* aHeaderField, nsAString& aData) const {
}
}
+static bool IsValidOnionLocation(nsIURI* aDocumentURI,
+ nsIURI* aOnionLocationURI) {
+ bool isHttpish;
+ nsAutoCString onionHost;
+ return aDocumentURI && aOnionLocationURI &&
+ NS_SUCCEEDED(aDocumentURI->SchemeIs("https", &isHttpish)) &&
+ isHttpish &&
+ ((NS_SUCCEEDED(aOnionLocationURI->SchemeIs("http", &isHttpish)) &&
+ isHttpish) ||
+ (NS_SUCCEEDED(aOnionLocationURI->SchemeIs("https", &isHttpish)) &&
+ isHttpish)) &&
+ NS_SUCCEEDED(aOnionLocationURI->GetAsciiHost(onionHost)) &&
+ StringEndsWith(onionHost, NS_LITERAL_CSTRING(".onion"));
+}
+
void Document::SetHeaderData(nsAtom* aHeaderField, const nsAString& aData) {
if (!aHeaderField) {
NS_ERROR("null headerField");
@@ -3834,6 +3850,20 @@ void Document::SetHeaderData(nsAtom* aHeaderField, const nsAString& aData) {
mReferrerPolicySet = true;
}
}
+ if (aHeaderField == nsGkAtoms::headerOnionLocation && !aData.IsEmpty()) {
+ nsCOMPtr<nsIURI> onionURI;
+ if (NS_SUCCEEDED(NS_NewURI(getter_AddRefs(onionURI), aData)) &&
+ IsValidOnionLocation(Document::GetDocumentURI(), onionURI)) {
+ if (StaticPrefs::privacy_prioritizeOnions()) {
+ nsCOMPtr<nsIRefreshURI> refresher(mDocumentContainer);
+ if (refresher) {
+ refresher->RefreshURI(onionURI, NodePrincipal(), 0, false, true);
+ }
+ } else {
+ mOnionLocationURI = onionURI;
+ }
+ }
+ }
}
void Document::TryChannelCharset(nsIChannel* aChannel, int32_t& aCharsetSource,
NotNull<const Encoding*>& aEncoding,
@@ -7468,7 +7498,7 @@ void Document::RetrieveRelevantHeaders(nsIChannel* aChannel) {
static const char* const headers[] = {
"default-style", "content-style-type", "content-language",
"content-disposition", "refresh", "x-dns-prefetch-control",
- "x-frame-options", "referrer-policy",
+ "x-frame-options", "referrer-policy", "onion-location",
// add more http headers if you need
// XXXbz don't add content-location support without reading bug
// 238654 and its dependencies/dups first.
diff --git a/dom/base/Document.h b/dom/base/Document.h
index 58d09afba815..43f8517fcd65 100644
--- a/dom/base/Document.h
+++ b/dom/base/Document.h
@@ -3291,6 +3291,7 @@ class Document : public nsINode,
void ReleaseCapture() const;
void MozSetImageElement(const nsAString& aImageElementId, Element* aElement);
nsIURI* GetDocumentURIObject() const;
+ nsIURI* GetOnionLocationURI() const { return mOnionLocationURI; }
// Not const because all the fullscreen goop is not const
bool FullscreenEnabled(CallerType aCallerType);
Element* FullscreenStackTop();
@@ -3998,6 +3999,7 @@ class Document : public nsINode,
nsCOMPtr<nsIURI> mChromeXHRDocURI;
nsCOMPtr<nsIURI> mDocumentBaseURI;
nsCOMPtr<nsIURI> mChromeXHRDocBaseURI;
+ nsCOMPtr<nsIURI> mOnionLocationURI;
// The base domain of the document for third-party checks.
nsCString mBaseDomain;
diff --git a/dom/webidl/Document.webidl b/dom/webidl/Document.webidl
index 0170a17fbf96..a281b04a0960 100644
--- a/dom/webidl/Document.webidl
+++ b/dom/webidl/Document.webidl
@@ -589,3 +589,12 @@ partial interface Document {
[ChromeOnly]
void setRDMPaneOrientation(OrientationType type, float rotationAngle);
};
+
+
+/**
+ * Extension to allows chrome JS to know whether the document has a valid
+ * Onion-Location that we could redirect to.
+ */
+partial interface Document {
+ [ChromeOnly] readonly attribute URI? onionLocationURI;
+};
diff --git a/modules/libpref/init/StaticPrefList.h b/modules/libpref/init/StaticPrefList.h
index 47f4626f7e6b..158952041d3d 100644
--- a/modules/libpref/init/StaticPrefList.h
+++ b/modules/libpref/init/StaticPrefList.h
@@ -2555,6 +2555,13 @@ VARCACHE_PREF(
)
#undef PREF_VALUE
+// Automatically redirect to Onion-Location header, disabled by default
+VARCACHE_PREF(
+ "privacy.prioritizeonions.enabled",
+ privacy_prioritizeOnions,
+ RelaxedAtomicBool, false
+)
+
// Anti-fingerprinting, disabled by default
VARCACHE_PREF(
"privacy.resistFingerprinting",
diff --git a/xpcom/ds/StaticAtoms.py b/xpcom/ds/StaticAtoms.py
index 9a182d3bf6d0..71fffc55f1b8 100644
--- a/xpcom/ds/StaticAtoms.py
+++ b/xpcom/ds/StaticAtoms.py
@@ -803,6 +803,7 @@ STATIC_ATOMS = [
Atom("oninput", "oninput"),
Atom("oninstall", "oninstall"),
Atom("oninvalid", "oninvalid"),
+ Atom("headerOnionLocation", "onion-location"),
Atom("onkeydown", "onkeydown"),
Atom("onkeypress", "onkeypress"),
Atom("onkeyup", "onkeyup"),
1
0
[tor-browser/tor-browser-68.6.0esr-9.5-1] Bug 28005: Implement .onion alias urlbar rewrites
by sysrqb@torproject.org 03 Apr '20
by sysrqb@torproject.org 03 Apr '20
03 Apr '20
commit 7306a08365be9212f621b396513352d19549c487
Author: Alex Catarineu <acat(a)torproject.org>
Date: Thu Feb 13 13:24:33 2020 +0100
Bug 28005: Implement .onion alias urlbar rewrites
A custom HTTPS Everywhere update channel is installed,
which provides rules for locally redirecting some memorable
.tor.onion URLs to non-memorable .onion URLs.
When these redirects occur, we also rewrite the URL in the urlbar
to display the human-memorable hostname instead of the actual
.onion.
---
browser/actors/ClickHandlerChild.jsm | 20 +++
browser/actors/ContextMenuChild.jsm | 4 +
browser/base/content/browser-places.js | 12 +-
browser/base/content/browser.js | 37 +++-
browser/base/content/nsContextMenu.js | 18 ++
browser/base/content/tabbrowser.js | 7 +
browser/base/content/utilityOverlay.js | 2 +
browser/components/BrowserGlue.jsm | 6 +
.../onionservices/ExtensionMessaging.jsm | 86 +++++++++
.../onionservices/HttpsEverywhereControl.jsm | 119 ++++++++++++
.../components/onionservices/OnionAliasStore.jsm | 199 +++++++++++++++++++++
browser/components/onionservices/moz.build | 6 +
browser/components/urlbar/UrlbarInput.jsm | 8 +-
browser/modules/ContentClick.jsm | 1 +
docshell/base/nsDocShell.cpp | 37 ++++
docshell/base/nsDocShell.h | 4 +
docshell/base/nsDocShellLoadState.cpp | 4 +
docshell/base/nsIDocShell.idl | 5 +
docshell/base/nsIWebNavigation.idl | 5 +
docshell/shistory/nsISHEntry.idl | 5 +
docshell/shistory/nsSHEntry.cpp | 18 +-
docshell/shistory/nsSHEntry.h | 1 +
modules/libpref/init/StaticPrefList.h | 7 +
netwerk/dns/effective_tld_names.dat | 2 +
.../remotebrowserutils/RemoteWebNavigation.jsm | 1 +
toolkit/content/widgets/browser-custom-element.js | 9 +
toolkit/modules/RemoteWebProgress.jsm | 2 +
toolkit/modules/WebProgressChild.jsm | 1 +
toolkit/modules/sessionstore/SessionHistory.jsm | 5 +
29 files changed, 622 insertions(+), 9 deletions(-)
diff --git a/browser/actors/ClickHandlerChild.jsm b/browser/actors/ClickHandlerChild.jsm
index 4375be0067ac..263a5fea053e 100644
--- a/browser/actors/ClickHandlerChild.jsm
+++ b/browser/actors/ClickHandlerChild.jsm
@@ -156,6 +156,26 @@ class ClickHandlerChild extends ActorChild {
json.originPrincipal = ownerDoc.nodePrincipal;
json.triggeringPrincipal = ownerDoc.nodePrincipal;
+ // Check if the link needs to be opened with .tor.onion urlbar rewrites
+ // allowed. Only when the owner doc has allowOnionUrlbarRewrites = true
+ // and the same origin we should allow this.
+ json.allowOnionUrlbarRewrites = false;
+ if (this.mm.docShell.allowOnionUrlbarRewrites) {
+ const sm = Services.scriptSecurityManager;
+ try {
+ let targetURI = Services.io.newURI(href);
+ let isPrivateWin =
+ ownerDoc.nodePrincipal.originAttributes.privateBrowsingId > 0;
+ sm.checkSameOriginURI(
+ docshell.currentDocumentChannel.URI,
+ targetURI,
+ false,
+ isPrivateWin
+ );
+ json.allowOnionUrlbarRewrites = true;
+ } catch (e) {}
+ }
+
// If a link element is clicked with middle button, user wants to open
// the link somewhere rather than pasting clipboard content. Therefore,
// when it's clicked with middle button, we should prevent multiple
diff --git a/browser/actors/ContextMenuChild.jsm b/browser/actors/ContextMenuChild.jsm
index 546f51e843d6..5915832eae7a 100644
--- a/browser/actors/ContextMenuChild.jsm
+++ b/browser/actors/ContextMenuChild.jsm
@@ -543,6 +543,9 @@ class ContextMenuChild extends ActorChild {
// The same-origin check will be done in nsContextMenu.openLinkInTab.
let parentAllowsMixedContent = !!this.docShell.mixedContentChannel;
+ let parentAllowsOnionUrlbarRewrites = this.docShell
+ .allowOnionUrlbarRewrites;
+
// Get referrer attribute from clicked link and parse it
let referrerAttrValue = Services.netUtils.parseAttributePolicyString(
aEvent.composedTarget.getAttribute("referrerpolicy")
@@ -659,6 +662,7 @@ class ContextMenuChild extends ActorChild {
popupNodeSelectors,
disableSetDesktopBg,
parentAllowsMixedContent,
+ parentAllowsOnionUrlbarRewrites,
};
Services.obs.notifyObservers(
diff --git a/browser/base/content/browser-places.js b/browser/base/content/browser-places.js
index 6aa348c609a4..a2dd38a97514 100755
--- a/browser/base/content/browser-places.js
+++ b/browser/base/content/browser-places.js
@@ -440,7 +440,8 @@ var PlacesCommandHook = {
*/
async bookmarkPage() {
let browser = gBrowser.selectedBrowser;
- let url = new URL(browser.currentURI.spec);
+ const uri = browser.currentOnionAliasURI || browser.currentURI;
+ let url = new URL(uri.spec);
let info = await PlacesUtils.bookmarks.fetch({ url });
let isNewBookmark = !info;
let showEditUI = !isNewBookmark || StarUI.showForNewBookmarks;
@@ -544,7 +545,7 @@ var PlacesCommandHook = {
tabs.forEach(tab => {
let browser = tab.linkedBrowser;
- let uri = browser.currentURI;
+ let uri = browser.currentOnionAliasURI || browser.currentURI;
let title = browser.contentTitle || tab.label;
let spec = uri.spec;
if (!(spec in uniquePages)) {
@@ -1618,14 +1619,17 @@ var BookmarkingUI = {
},
onLocationChange: function BUI_onLocationChange() {
- if (this._uri && gBrowser.currentURI.equals(this._uri)) {
+ const uri =
+ gBrowser.selectedBrowser.currentOnionAliasURI || gBrowser.currentURI;
+ if (this._uri && uri.equals(this._uri)) {
return;
}
this.updateStarState();
},
updateStarState: function BUI_updateStarState() {
- this._uri = gBrowser.currentURI;
+ this._uri =
+ gBrowser.selectedBrowser.currentOnionAliasURI || gBrowser.currentURI;
this._itemGuids.clear();
let guids = new Set();
diff --git a/browser/base/content/browser.js b/browser/base/content/browser.js
index 3f9bf006f562..2c89d658d4ec 100644
--- a/browser/base/content/browser.js
+++ b/browser/base/content/browser.js
@@ -72,6 +72,7 @@ XPCOMUtils.defineLazyModuleGetters(this, {
TabCrashHandler: "resource:///modules/ContentCrashHandlers.jsm",
TelemetryEnvironment: "resource://gre/modules/TelemetryEnvironment.jsm",
Translation: "resource:///modules/translation/Translation.jsm",
+ OnionAliasStore: "resource:///modules/OnionAliasStore.jsm",
UITour: "resource:///modules/UITour.jsm",
UpdateUtils: "resource://gre/modules/UpdateUtils.jsm",
UrlbarInput: "resource:///modules/UrlbarInput.jsm",
@@ -3335,7 +3336,10 @@ function URLBarSetURI(aURI, updatePopupNotifications) {
// bar if the user has deleted the URL and we'd just put the same URL
// back. See bug 304198.
if (value === null) {
- let uri = aURI || gBrowser.currentURI;
+ let uri =
+ aURI ||
+ gBrowser.selectedBrowser.currentOnionAliasURI ||
+ gBrowser.currentURI;
// Strip off usernames and passwords for the location bar
try {
uri = Services.uriFixup.createExposableURI(uri);
@@ -5897,11 +5901,24 @@ var XULBrowserWindow = {
this.reloadCommand.removeAttribute("disabled");
}
+ // The onion memorable alias needs to be used in URLBarSetURI, but also in
+ // other parts of the code (like the bookmarks UI), so we save it.
+ if (gBrowser.selectedBrowser.allowOnionUrlbarRewrites) {
+ gBrowser.selectedBrowser.currentOnionAliasURI = OnionAliasStore.getShortURI(
+ aLocationURI
+ );
+ } else {
+ gBrowser.selectedBrowser.currentOnionAliasURI = null;
+ }
+
// We want to update the popup visibility if we received this notification
// via simulated locationchange events such as switching between tabs, however
// if this is a document navigation then PopupNotifications will be updated
// via TabsProgressListener.onLocationChange and we do not want it called twice
- URLBarSetURI(aLocationURI, aIsSimulated);
+ URLBarSetURI(
+ gBrowser.selectedBrowser.currentOnionAliasURI || aLocationURI,
+ aIsSimulated
+ );
BookmarkingUI.onLocationChange();
@@ -7627,6 +7644,21 @@ function handleLinkClick(event, href, linkNode) {
} catch (e) {}
}
+ // Check if the link needs to be opened with .tor.onion urlbar rewrites
+ // allowed. Only when the owner doc has allowOnionUrlbarRewrites = true
+ // and the same origin we should allow this.
+ let persistAllowOnionUrlbarRewritesInChildTab = false;
+ if (where == "tab" && gBrowser.docShell.allowOnionUrlbarRewrites) {
+ const sm = Services.scriptSecurityManager;
+ try {
+ let tURI = makeURI(href);
+ let isPrivateWin =
+ doc.nodePrincipal.originAttributes.privateBrowsingId > 0;
+ sm.checkSameOriginURI(referrerURI, tURI, false, isPrivateWin);
+ persistAllowOnionUrlbarRewritesInChildTab = true;
+ } catch (e) {}
+ }
+
// first get document wide referrer policy, then
// get referrer attribute from clicked link and parse it and
// allow per element referrer to overrule the document wide referrer if enabled
@@ -7659,6 +7691,7 @@ function handleLinkClick(event, href, linkNode) {
triggeringPrincipal: doc.nodePrincipal,
csp,
frameOuterWindowID,
+ allowOnionUrlbarRewrites: persistAllowOnionUrlbarRewritesInChildTab,
};
// The new tab/window must use the same userContextId
diff --git a/browser/base/content/nsContextMenu.js b/browser/base/content/nsContextMenu.js
index e7106e5e8fc1..55da2efb7782 100644
--- a/browser/base/content/nsContextMenu.js
+++ b/browser/base/content/nsContextMenu.js
@@ -93,6 +93,7 @@ function openContextMenu(aMessage) {
disableSetDesktopBackground: data.disableSetDesktopBg,
loginFillInfo: data.loginFillInfo,
parentAllowsMixedContent: data.parentAllowsMixedContent,
+ parentAllowsOnionUrlbarRewrites: data.parentAllowsOnionUrlbarRewrites,
userContextId: data.userContextId,
webExtContextData: data.webExtContextData,
};
@@ -1122,9 +1123,26 @@ nsContextMenu.prototype = {
} catch (e) {}
}
+ // Check if the link needs to be opened with .tor.onion urlbar rewrites
+ // allowed. Only when parent has allowOnionUrlbarRewrites = true
+ // and the same origin we should allow this.
+ let persistAllowOnionUrlbarRewrites = false;
+
+ if (gContextMenuContentData.parentAllowsOnionUrlbarRewrites) {
+ const sm = Services.scriptSecurityManager;
+ try {
+ let targetURI = this.linkURI;
+ let isPrivateWin =
+ this.browser.contentPrincipal.originAttributes.privateBrowsingId > 0;
+ sm.checkSameOriginURI(referrerURI, targetURI, false, isPrivateWin);
+ persistAllowOnionUrlbarRewrites = true;
+ } catch (e) {}
+ }
+
let params = {
allowMixedContent: persistAllowMixedContentInChildTab,
userContextId: parseInt(event.target.getAttribute("data-usercontextid")),
+ allowOnionUrlbarRewrites: persistAllowOnionUrlbarRewrites,
};
openLinkIn(this.linkURL, "tab", this._openLinkInParameters(params));
diff --git a/browser/base/content/tabbrowser.js b/browser/base/content/tabbrowser.js
index 4dd07ff14e7b..53c463fd3263 100644
--- a/browser/base/content/tabbrowser.js
+++ b/browser/base/content/tabbrowser.js
@@ -1589,6 +1589,7 @@
var aRelatedToCurrent;
var aAllowInheritPrincipal;
var aAllowMixedContent;
+ var aAllowOnionUrlbarRewrites;
var aSkipAnimation;
var aForceNotRemote;
var aPreferredRemoteType;
@@ -1618,6 +1619,7 @@
aRelatedToCurrent = params.relatedToCurrent;
aAllowInheritPrincipal = !!params.allowInheritPrincipal;
aAllowMixedContent = params.allowMixedContent;
+ aAllowOnionUrlbarRewrites = params.allowOnionUrlbarRewrites;
aSkipAnimation = params.skipAnimation;
aForceNotRemote = params.forceNotRemote;
aPreferredRemoteType = params.preferredRemoteType;
@@ -1658,6 +1660,7 @@
relatedToCurrent: aRelatedToCurrent,
skipAnimation: aSkipAnimation,
allowMixedContent: aAllowMixedContent,
+ allowOnionUrlbarRewrites: aAllowOnionUrlbarRewrites,
forceNotRemote: aForceNotRemote,
createLazyBrowser: aCreateLazyBrowser,
preferredRemoteType: aPreferredRemoteType,
@@ -2530,6 +2533,7 @@
{
allowInheritPrincipal,
allowMixedContent,
+ allowOnionUrlbarRewrites,
allowThirdPartyFixup,
bulkOrderedOpen,
charset,
@@ -2902,6 +2906,9 @@
if (allowMixedContent) {
flags |= Ci.nsIWebNavigation.LOAD_FLAGS_ALLOW_MIXED_CONTENT;
}
+ if (allowOnionUrlbarRewrites) {
+ flags |= Ci.nsIWebNavigation.LOAD_FLAGS_ALLOW_ONION_URLBAR_REWRITES;
+ }
if (!allowInheritPrincipal) {
flags |= Ci.nsIWebNavigation.LOAD_FLAGS_DISALLOW_INHERIT_PRINCIPAL;
}
diff --git a/browser/base/content/utilityOverlay.js b/browser/base/content/utilityOverlay.js
index 9a1010b2afa9..cc46b14561b4 100644
--- a/browser/base/content/utilityOverlay.js
+++ b/browser/base/content/utilityOverlay.js
@@ -370,6 +370,7 @@ function openLinkIn(url, where, params) {
var aRelatedToCurrent = params.relatedToCurrent;
var aAllowInheritPrincipal = !!params.allowInheritPrincipal;
var aAllowMixedContent = params.allowMixedContent;
+ var aAllowOnionUrlbarRewrites = params.allowOnionUrlbarRewrites;
var aForceAllowDataURI = params.forceAllowDataURI;
var aInBackground = params.inBackground;
var aInitiatingDoc = params.initiatingDoc;
@@ -680,6 +681,7 @@ function openLinkIn(url, where, params) {
relatedToCurrent: aRelatedToCurrent,
skipAnimation: aSkipTabAnimation,
allowMixedContent: aAllowMixedContent,
+ allowOnionUrlbarRewrites: aAllowOnionUrlbarRewrites,
userContextId: aUserContextId,
originPrincipal: aPrincipal,
triggeringPrincipal: aTriggeringPrincipal,
diff --git a/browser/components/BrowserGlue.jsm b/browser/components/BrowserGlue.jsm
index 4e851289fbe9..628c6f5db151 100644
--- a/browser/components/BrowserGlue.jsm
+++ b/browser/components/BrowserGlue.jsm
@@ -494,6 +494,7 @@ XPCOMUtils.defineLazyModuleGetters(this, {
ShellService: "resource:///modules/ShellService.jsm",
TabCrashHandler: "resource:///modules/ContentCrashHandlers.jsm",
TabUnloader: "resource:///modules/TabUnloader.jsm",
+ OnionAliasStore: "resource:///modules/OnionAliasStore.jsm",
UIState: "resource://services-sync/UIState.jsm",
UITour: "resource:///modules/UITour.jsm",
WebChannel: "resource://gre/modules/WebChannel.jsm",
@@ -1839,6 +1840,7 @@ BrowserGlue.prototype = {
Normandy.uninit();
RFPHelper.uninit();
+ OnionAliasStore.uninit();
},
// Set up a listener to enable/disable the screenshots extension
@@ -2109,6 +2111,10 @@ BrowserGlue.prototype = {
RFPHelper.init();
});
+ Services.tm.idleDispatchToMainThread(() => {
+ OnionAliasStore.init();
+ });
+
ChromeUtils.idleDispatch(() => {
Blocklist.loadBlocklistAsync();
});
diff --git a/browser/components/onionservices/ExtensionMessaging.jsm b/browser/components/onionservices/ExtensionMessaging.jsm
new file mode 100644
index 000000000000..b5d69df93807
--- /dev/null
+++ b/browser/components/onionservices/ExtensionMessaging.jsm
@@ -0,0 +1,86 @@
+// Copyright (c) 2020, The Tor Project, Inc.
+
+"use strict";
+
+const EXPORTED_SYMBOLS = ["ExtensionMessaging"];
+
+const { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm");
+const { ExtensionUtils } = ChromeUtils.import(
+ "resource://gre/modules/ExtensionUtils.jsm"
+);
+const { MessageChannel } = ChromeUtils.import(
+ "resource://gre/modules/MessageChannel.jsm"
+);
+const { AddonManager } = ChromeUtils.import(
+ "resource://gre/modules/AddonManager.jsm"
+);
+
+class ExtensionMessaging {
+ constructor() {
+ this._callback = null;
+ this._handlers = new Map();
+ this._messageManager = Services.cpmm;
+ }
+
+ async sendMessage(msg, extensionId) {
+ this._init();
+
+ const addon = await AddonManager.getAddonByID(extensionId);
+ if (!addon) {
+ throw new Error(`extension '${extensionId} does not exist`);
+ }
+ await addon.startupPromise;
+
+ const channelId = ExtensionUtils.getUniqueId();
+ return new Promise((resolve, reject) => {
+ this._handlers.set(channelId, { resolve, reject });
+ this._messageManager.sendAsyncMessage("MessageChannel:Messages", [
+ {
+ messageName: "Extension:Message",
+ sender: {
+ id: extensionId,
+ extensionId,
+ },
+ recipient: { extensionId },
+ data: new StructuredCloneHolder(msg),
+ channelId,
+ responseType: MessageChannel.RESPONSE_FIRST,
+ },
+ ]);
+ });
+ }
+
+ unload() {
+ if (this._callback) {
+ this._handlers.clear();
+ this._messageManager.removeMessageListener(
+ "MessageChannel:Response",
+ this._callback
+ );
+ this._callback = null;
+ }
+ }
+
+ _onMessage({ data }) {
+ const channelId = data.messageName;
+ if (this._handlers.has(channelId)) {
+ const { resolve, reject } = this._handlers.get(channelId);
+ this._handlers.delete(channelId);
+ if (data.error) {
+ reject(new Error(data.error.message));
+ } else {
+ resolve(data.value);
+ }
+ }
+ }
+
+ _init() {
+ if (this._callback === null) {
+ this._callback = this._onMessage.bind(this);
+ this._messageManager.addMessageListener(
+ "MessageChannel:Response",
+ this._callback
+ );
+ }
+ }
+}
diff --git a/browser/components/onionservices/HttpsEverywhereControl.jsm b/browser/components/onionservices/HttpsEverywhereControl.jsm
new file mode 100644
index 000000000000..87954461bab1
--- /dev/null
+++ b/browser/components/onionservices/HttpsEverywhereControl.jsm
@@ -0,0 +1,119 @@
+// Copyright (c) 2020, The Tor Project, Inc.
+
+"use strict";
+
+const EXPORTED_SYMBOLS = ["HttpsEverywhereControl"];
+
+const { ExtensionMessaging } = ChromeUtils.import(
+ "resource:///modules/ExtensionMessaging.jsm"
+);
+const { setTimeout } = ChromeUtils.import("resource://gre/modules/Timer.jsm");
+
+const EXTENSION_ID = "https-everywhere-eff(a)eff.org";
+const SECUREDROP_TOR_ONION_CHANNEL = {
+ name: "SecureDropTorOnion",
+ jwk: {
+ kty: "RSA",
+ e: "AQAB",
+ n:
+ "y0iWTVev1uYDVhLdc5uSHWke-9JlbxzqIsGkS95Pk5NsxdlkdbHpqaPr-5xL5FspX8QGo3HAT5hrUcPV_kz8x-HwGEm2-p9BQ6-yEPtr5QXQGGzNoizmj7HH-b0y5qx8iUFwAJ__PJWK4IwSgjIQqHMjmkOLc9N4bmRPULi6ZZMb-97FdeZsh34dVy2tpIzZaijRfRQSfeZkwRXZzOY-siGfOAzY_UcrHFli5zroTZAyDaetFm1z2-TdFLOvN8fi0o3mBbCB9SqhOUImPwSTNWTp2D6bHhI91mt7gr6fLnzHMGrTMh2DQ4vjt_98pe7WTUzuRCLa9Awb6JJgbYA4ySV1akAU0_iq6oCAE9PZbUgUw9UAH1ctRFml87F3HORUMMj5ZCLwRIrEXqrCJbV4f-Ius-ZO2wwlYTsEv8TmUzISpMwVjGOIpXwFIb65R_EX3_vIopauSoyZkvk3klly0Qe6KTy_gg1CZ_h2ZXPpLMwqlfFTDBPv2q8gyuzgkYXQes3FX-PbJ9Dsl5QO4icuEjV2NQ7iPwwIPAtj9cpqCD8-p9TqTKaZjOFC9-ryJpWsivGCbvN2JotmJ5Ax9rmnAMvQM09muCetFj_ZIgllcpeahaw6gxVXlSYIhb0J9V878KNuRJ2yPJFlBmgpFexvCcz8Jqs6JUfIrmUAGUXG9nE",
+ },
+ update_path_prefix: "https://redshiftzero.github.io/securedrop-httpse/",
+ scope:
+ "^https?:\\/\\/[a-z0-9-]+(?:\\.[a-z0-9-]+)*\\.securedrop\\.tor\\.onion\\/",
+ replaces_default_rulesets: false,
+};
+
+class HttpsEverywhereControl {
+ constructor() {
+ this._extensionMessaging = null;
+ }
+
+ async _sendMessage(type, object) {
+ return this._extensionMessaging.sendMessage(
+ {
+ type,
+ object,
+ },
+ EXTENSION_ID
+ );
+ }
+
+ static async wait(seconds = 1) {
+ return new Promise(resolve => setTimeout(resolve, seconds * 1000));
+ }
+
+ /**
+ * Installs the .tor.onion update channel in https-everywhere
+ */
+ async installTorOnionUpdateChannel(retries = 5) {
+ this._init();
+
+ // TODO: https-everywhere store is initialized asynchronously, so sending a message
+ // immediately results in a `store.get is undefined` error.
+ // For now, let's wait a bit and retry a few times if there is an error, but perhaps
+ // we could suggest https-everywhere to send a message when that happens and listen
+ // for that here.
+ await HttpsEverywhereControl.wait();
+
+ try {
+ // TODO: we may want a way to "lock" this update channel, so that it cannot be modified
+ // by the user via UI, but I think this is not possible at the time of writing via
+ // the existing messages in https-everywhere.
+ await this._sendMessage(
+ "create_update_channel",
+ SECUREDROP_TOR_ONION_CHANNEL.name
+ );
+ } catch (e) {
+ if (retries <= 0) {
+ throw new Error("Could not install SecureDropTorOnion update channel");
+ }
+ await this.installTorOnionUpdateChannel(retries - 1);
+ return;
+ }
+
+ await this._sendMessage(
+ "update_update_channel",
+ SECUREDROP_TOR_ONION_CHANNEL
+ );
+ }
+
+ /**
+ * Returns the .tor.onion rulesets available in https-everywhere
+ */
+ async getTorOnionRules() {
+ return this._sendMessage("get_simple_rules_ending_with", ".tor.onion");
+ }
+
+ /**
+ * Returns the timestamp of the last .tor.onion update channel update.
+ */
+ async getRulesetTimestamp() {
+ const rulesets = await this._sendMessage("get_ruleset_timestamps");
+ const securedrop =
+ rulesets &&
+ rulesets.find(([{ name }]) => name === SECUREDROP_TOR_ONION_CHANNEL.name);
+ if (securedrop) {
+ const [
+ updateChannel, // This has the same structure as SECUREDROP_TOR_ONION_CHANNEL
+ lastUpdatedTimestamp, // An integer, 0 if the update channel was never updated
+ ] = securedrop;
+ void updateChannel; // Ignore eslint unused warning for ruleset
+ return lastUpdatedTimestamp;
+ }
+ return null;
+ }
+
+ unload() {
+ if (this._extensionMessaging) {
+ this._extensionMessaging.unload();
+ this._extensionMessaging = null;
+ }
+ }
+
+ _init() {
+ if (!this._extensionMessaging) {
+ this._extensionMessaging = new ExtensionMessaging();
+ }
+ }
+}
diff --git a/browser/components/onionservices/OnionAliasStore.jsm b/browser/components/onionservices/OnionAliasStore.jsm
new file mode 100644
index 000000000000..7e006e59490b
--- /dev/null
+++ b/browser/components/onionservices/OnionAliasStore.jsm
@@ -0,0 +1,199 @@
+// Copyright (c) 2020, The Tor Project, Inc.
+
+"use strict";
+
+const EXPORTED_SYMBOLS = ["OnionAliasStore"];
+
+const { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm");
+const { XPCOMUtils } = ChromeUtils.import(
+ "resource://gre/modules/XPCOMUtils.jsm"
+);
+const { setTimeout, clearTimeout } = ChromeUtils.import(
+ "resource://gre/modules/Timer.jsm"
+);
+const { HttpsEverywhereControl } = ChromeUtils.import(
+ "resource:///modules/HttpsEverywhereControl.jsm"
+);
+
+// Logger adapted from CustomizableUI.jsm
+const kPrefOnionAliasDebug = "browser.onionalias.debug";
+XPCOMUtils.defineLazyPreferenceGetter(
+ this,
+ "gDebuggingEnabled",
+ kPrefOnionAliasDebug,
+ false,
+ (pref, oldVal, newVal) => {
+ if (typeof log != "undefined") {
+ log.maxLogLevel = newVal ? "all" : "log";
+ }
+ }
+);
+XPCOMUtils.defineLazyGetter(this, "log", () => {
+ let scope = {};
+ ChromeUtils.import("resource://gre/modules/Console.jsm", scope);
+ let consoleOptions = {
+ maxLogLevel: gDebuggingEnabled ? "all" : "log",
+ prefix: "OnionAlias",
+ };
+ return new scope.ConsoleAPI(consoleOptions);
+});
+
+function observe(topic, callback) {
+ let observer = {
+ observe(aSubject, aTopic, aData) {
+ if (topic === aTopic) {
+ callback(aSubject, aData);
+ }
+ },
+ };
+ Services.obs.addObserver(observer, topic);
+ return () => Services.obs.removeObserver(observer, topic);
+}
+
+class _OnionAliasStore {
+ static get RULESET_CHECK_INTERVAL() {
+ return 1000 * 60; // 1 minute
+ }
+
+ static get RULESET_CHECK_INTERVAL_FAST() {
+ return 1000 * 5; // 5 seconds
+ }
+
+ constructor() {
+ this._onionMap = new Map();
+ this._rulesetTimeout = null;
+ this._removeObserver = () => {};
+ this._canLoadRules = false;
+ this._rulesetTimestamp = null;
+ }
+
+ async _periodicRulesetCheck() {
+ // TODO: it would probably be preferable to listen to some message broadcasted by
+ // the https-everywhere extension when some update channel is updated, instead of
+ // polling every N seconds.
+ log.debug("Checking for new rules");
+ const ts = await this.httpsEverywhereControl.getRulesetTimestamp();
+ log.debug(
+ `Found ruleset timestamp ${ts}, current is ${this._rulesetTimestamp}`
+ );
+ if (ts !== this._rulesetTimestamp) {
+ this._rulesetTimestamp = ts;
+ log.debug("New rules found, updating");
+ // We clear the mappings even if we cannot load the rules from https-everywhere,
+ // since we cannot be sure if the stored mappings are correct anymore.
+ this._clear();
+ if (this._canLoadRules) {
+ await this._loadRules();
+ }
+ }
+ // If the timestamp is 0, that means the update channel was not yet updated, so
+ // we schedule a check soon.
+ this._rulesetTimeout = setTimeout(
+ () => this._periodicRulesetCheck(),
+ ts === 0
+ ? _OnionAliasStore.RULESET_CHECK_INTERVAL_FAST
+ : _OnionAliasStore.RULESET_CHECK_INTERVAL
+ );
+ }
+
+ async init() {
+ this.httpsEverywhereControl = new HttpsEverywhereControl();
+
+ // Install update channel
+ await this.httpsEverywhereControl.installTorOnionUpdateChannel();
+
+ // Setup .tor.onion rule loading.
+ // The http observer is a fallback, and is removed in _loadRules() as soon as we are able
+ // to load some rules from HTTPS Everywhere.
+ this._loadHttpObserver();
+ try {
+ await this.httpsEverywhereControl.getTorOnionRules();
+ this._canLoadRules = true;
+ } catch (e) {
+ // Loading rules did not work, probably because "get_simple_rules_ending_with" is not yet
+ // working in https-everywhere. Use an http observer as a fallback for learning the rules.
+ log.debug("Could not load rules, using http observer as fallback");
+ }
+
+ // Setup checker for https-everywhere ruleset updates
+ this._periodicRulesetCheck();
+ }
+
+ /**
+ * Loads the .tor.onion mappings from https-everywhere.
+ */
+ async _loadRules() {
+ const rules = await this.httpsEverywhereControl.getTorOnionRules();
+ // Remove http observer if we are able to load some rules directly.
+ if (rules.length) {
+ this._removeObserver();
+ this._removeObserver = () => {};
+ }
+ this._clear();
+ log.debug(`Loading ${rules.length} rules`, rules);
+ for (const rule of rules) {
+ // Here we are trusting that the securedrop ruleset follows some conventions so that we can
+ // assume there is a host mapping from `rule.host` to the hostname of the URL in `rule.to`.
+ try {
+ const url = new URL(rule.to);
+ const shortHost = rule.host;
+ const longHost = url.hostname;
+ this._addMapping(shortHost, longHost);
+ } catch (e) {
+ log.error("Could not process rule:", rule);
+ }
+ }
+ }
+
+ /**
+ * Loads a http observer to listen for local redirects for populating
+ * the .tor.onion -> .onion mappings. Should only be used if we cannot ask https-everywhere
+ * directly for the mappings.
+ */
+ _loadHttpObserver() {
+ this._removeObserver = observe("http-on-before-connect", channel => {
+ if (
+ channel.isMainDocumentChannel &&
+ channel.originalURI.host.endsWith(".tor.onion")
+ ) {
+ this._addMapping(channel.originalURI.host, channel.URI.host);
+ }
+ });
+ }
+
+ uninit() {
+ this._clear();
+ this._removeObserver();
+ this._removeObserver = () => {};
+ if (this.httpsEverywhereControl) {
+ this.httpsEverywhereControl.unload();
+ delete this.httpsEverywhereControl;
+ }
+ clearTimeout(this._rulesetTimeout);
+ this._rulesetTimeout = null;
+ this._rulesetTimestamp = null;
+ }
+
+ _clear() {
+ this._onionMap.clear();
+ }
+
+ _addMapping(shortOnionHost, longOnionHost) {
+ this._onionMap.set(longOnionHost, shortOnionHost);
+ }
+
+ getShortURI(onionURI) {
+ if (
+ (onionURI.schemeIs("http") || onionURI.schemeIs("https")) &&
+ this._onionMap.has(onionURI.host)
+ ) {
+ return onionURI
+ .mutate()
+ .setHost(this._onionMap.get(onionURI.host))
+ .finalize();
+ }
+ return null;
+ }
+}
+
+let OnionAliasStore = new _OnionAliasStore();
diff --git a/browser/components/onionservices/moz.build b/browser/components/onionservices/moz.build
index 7e103239c8d6..e4b6d73f8f40 100644
--- a/browser/components/onionservices/moz.build
+++ b/browser/components/onionservices/moz.build
@@ -1 +1,7 @@
JAR_MANIFESTS += ['jar.mn']
+
+EXTRA_JS_MODULES += [
+ 'ExtensionMessaging.jsm',
+ 'HttpsEverywhereControl.jsm',
+ 'OnionAliasStore.jsm',
+]
diff --git a/browser/components/urlbar/UrlbarInput.jsm b/browser/components/urlbar/UrlbarInput.jsm
index 131d2ecc8ca8..8fd87bb8b026 100644
--- a/browser/components/urlbar/UrlbarInput.jsm
+++ b/browser/components/urlbar/UrlbarInput.jsm
@@ -1022,7 +1022,13 @@ class UrlbarInput {
}
let uri;
- if (this.getAttribute("pageproxystate") == "valid") {
+ // When we rewrite .onion to an alias, gBrowser.currentURI will be different than
+ // the URI displayed in the urlbar. We need to use the urlbar value to copy the
+ // alias instead of the actual .onion URI that is loaded.
+ if (
+ this.getAttribute("pageproxystate") == "valid" &&
+ !this.window.gBrowser.selectedBrowser.allowOnionUrlbarRewrites
+ ) {
uri = this.window.gBrowser.currentURI;
} else {
// The value could be:
diff --git a/browser/modules/ContentClick.jsm b/browser/modules/ContentClick.jsm
index 767c67880995..872b06488c1a 100644
--- a/browser/modules/ContentClick.jsm
+++ b/browser/modules/ContentClick.jsm
@@ -88,6 +88,7 @@ var ContentClick = {
charset: browser.characterSet,
referrerInfo: E10SUtils.deserializeReferrerInfo(json.referrerInfo),
allowMixedContent: json.allowMixedContent,
+ allowOnionUrlbarRewrites: json.allowOnionUrlbarRewrites,
isContentWindowPrivate: json.isContentWindowPrivate,
originPrincipal: json.originPrincipal,
triggeringPrincipal: json.triggeringPrincipal,
diff --git a/docshell/base/nsDocShell.cpp b/docshell/base/nsDocShell.cpp
index cc329a50c109..80678a04e95c 100644
--- a/docshell/base/nsDocShell.cpp
+++ b/docshell/base/nsDocShell.cpp
@@ -6543,6 +6543,18 @@ void nsDocShell::OnRedirectStateChange(nsIChannel* aOldChannel,
return;
}
+ if (!mAllowOnionUrlbarRewrites) {
+ nsAutoCString oldHost;
+ nsAutoCString newHost;
+ if (NS_SUCCEEDED(oldURI->GetHost(oldHost)) &&
+ StringEndsWith(oldHost, NS_LITERAL_CSTRING(".tor.onion")) &&
+ NS_SUCCEEDED(newURI->GetHost(newHost)) &&
+ StringEndsWith(newHost, NS_LITERAL_CSTRING(".onion")) &&
+ !StringEndsWith(newHost, NS_LITERAL_CSTRING(".tor.onion"))) {
+ mAllowOnionUrlbarRewrites = true;
+ }
+ }
+
// Below a URI visit is saved (see AddURIVisit method doc).
// The visit chain looks something like:
// ...
@@ -9744,6 +9756,10 @@ nsresult nsDocShell::InternalLoad(nsDocShellLoadState* aLoadState,
// We're making history navigation or a reload. Make sure our history ID
// points to the same ID as SHEntry's docshell ID.
mHistoryID = aLoadState->SHEntry()->DocshellID();
+ // Loading from session history may not call DoURILoad(), so we set this
+ // flag here.
+ mAllowOnionUrlbarRewrites = aLoadState->HasLoadFlags(
+ INTERNAL_LOAD_FLAGS_ALLOW_ONION_URLBAR_REWRITES);
}
}
@@ -10386,6 +10402,13 @@ nsresult nsDocShell::DoURILoad(nsDocShellLoadState* aLoadState,
}
}
+ mAllowOnionUrlbarRewrites =
+ aLoadState->HasLoadFlags(
+ INTERNAL_LOAD_FLAGS_ALLOW_ONION_URLBAR_REWRITES) ||
+ (mAllowOnionUrlbarRewrites && GetCurrentDocChannel() &&
+ NS_SUCCEEDED(
+ nsContentUtils::CheckSameOrigin(GetCurrentDocChannel(), channel)));
+
// hack
nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(channel));
nsCOMPtr<nsIHttpChannelInternal> httpChannelInternal(
@@ -11733,6 +11756,7 @@ nsresult nsDocShell::AddToSessionHistory(nsIURI* aURI, nsIChannel* aChannel,
triggeringPrincipal, // Channel or provided principal
principalToInherit, csp, mHistoryID, mDynamicallyCreated);
+ entry->SetAllowOnionUrlbarRewrites(mAllowOnionUrlbarRewrites);
entry->SetOriginalURI(originalURI);
entry->SetResultPrincipalURI(resultPrincipalURI);
entry->SetLoadReplace(loadReplace);
@@ -11913,6 +11937,10 @@ nsresult nsDocShell::LoadHistoryEntry(nsISHEntry* aEntry, uint32_t aLoadType) {
srcdoc = VoidString();
}
+ if (aEntry->GetAllowOnionUrlbarRewrites()) {
+ flags |= INTERNAL_LOAD_FLAGS_ALLOW_ONION_URLBAR_REWRITES;
+ }
+
// If there is no valid triggeringPrincipal, we deny the load
MOZ_ASSERT(triggeringPrincipal,
"need a valid triggeringPrincipal to load from history");
@@ -13817,3 +13845,12 @@ nsDocShell::SetWatchedByDevtools(bool aWatched) {
mWatchedByDevtools = aWatched;
return NS_OK;
}
+
+NS_IMETHODIMP
+nsDocShell::GetAllowOnionUrlbarRewrites(bool* aAllowOnionUrlbarRewrites) {
+ NS_ENSURE_ARG(aAllowOnionUrlbarRewrites);
+ *aAllowOnionUrlbarRewrites =
+ StaticPrefs::browser_urlbar_onionRewrites_enabled() &&
+ mAllowOnionUrlbarRewrites;
+ return NS_OK;
+}
diff --git a/docshell/base/nsDocShell.h b/docshell/base/nsDocShell.h
index 4a81946f7bf4..7de079c0903e 100644
--- a/docshell/base/nsDocShell.h
+++ b/docshell/base/nsDocShell.h
@@ -153,6 +153,9 @@ class nsDocShell final : public nsDocLoader,
// Whether the load was triggered by user interaction.
INTERNAL_LOAD_FLAGS_IS_USER_TRIGGERED = 0x1000,
+
+ // Whether rewriting the urlbar to a short .onion alias is allowed.
+ INTERNAL_LOAD_FLAGS_ALLOW_ONION_URLBAR_REWRITES = 0x2000,
};
// Event type dispatched by RestorePresentation
@@ -1235,6 +1238,7 @@ class nsDocShell final : public nsDocLoader,
bool mCSSErrorReportingEnabled : 1;
bool mAllowAuth : 1;
bool mAllowKeywordFixup : 1;
+ bool mAllowOnionUrlbarRewrites : 1;
bool mIsOffScreenBrowser : 1;
bool mIsActive : 1;
bool mDisableMetaRefreshWhenInactive : 1;
diff --git a/docshell/base/nsDocShellLoadState.cpp b/docshell/base/nsDocShellLoadState.cpp
index d2e21edceeda..80143b49f3fa 100644
--- a/docshell/base/nsDocShellLoadState.cpp
+++ b/docshell/base/nsDocShellLoadState.cpp
@@ -417,6 +417,10 @@ void nsDocShellLoadState::CalculateLoadURIFlags() {
mLoadFlags |= nsDocShell::INTERNAL_LOAD_FLAGS_ALLOW_THIRD_PARTY_FIXUP;
}
+ if (oldLoadFlags & nsIWebNavigation::LOAD_FLAGS_ALLOW_ONION_URLBAR_REWRITES) {
+ mLoadFlags |= nsDocShell::INTERNAL_LOAD_FLAGS_ALLOW_ONION_URLBAR_REWRITES;
+ }
+
if (oldLoadFlags & nsIWebNavigation::LOAD_FLAGS_FIRST_LOAD) {
mLoadFlags |= nsDocShell::INTERNAL_LOAD_FLAGS_FIRST_LOAD;
}
diff --git a/docshell/base/nsIDocShell.idl b/docshell/base/nsIDocShell.idl
index 542232892c5b..cc0013e80c10 100644
--- a/docshell/base/nsIDocShell.idl
+++ b/docshell/base/nsIDocShell.idl
@@ -1195,4 +1195,9 @@ interface nsIDocShell : nsIDocShellTreeItem
* Whether developer tools are watching activity in this docshell.
*/
[infallible] attribute boolean watchedByDevtools;
+
+ /**
+ * Whether rewriting the urlbar to a short .onion alias is allowed.
+ */
+ [infallible] readonly attribute boolean allowOnionUrlbarRewrites;
};
diff --git a/docshell/base/nsIWebNavigation.idl b/docshell/base/nsIWebNavigation.idl
index cabae3f31d0f..123129d2c259 100644
--- a/docshell/base/nsIWebNavigation.idl
+++ b/docshell/base/nsIWebNavigation.idl
@@ -227,6 +227,11 @@ interface nsIWebNavigation : nsISupports
const unsigned long LOAD_FLAGS_IS_REDIRECT = 0x800000;
/**
+ * Allow rewriting the urlbar to a short .onion alias.
+ */
+ const unsigned long LOAD_FLAGS_ALLOW_ONION_URLBAR_REWRITES = 0x1000000;
+
+ /**
* Loads a given URI. This will give priority to loading the requested URI
* in the object implementing this interface. If it can't be loaded here
* however, the URI dispatcher will go through its normal process of content
diff --git a/docshell/shistory/nsISHEntry.idl b/docshell/shistory/nsISHEntry.idl
index 12dbf8172262..f5863b532a28 100644
--- a/docshell/shistory/nsISHEntry.idl
+++ b/docshell/shistory/nsISHEntry.idl
@@ -230,6 +230,11 @@ interface nsISHEntry : nsISupports
[infallible] attribute boolean persist;
/**
+ * Whether rewriting the urlbar to a short .onion alias is allowed.
+ */
+ [infallible] attribute boolean allowOnionUrlbarRewrites;
+
+ /**
* Set/Get the visual viewport scroll position if session history is
* changed through anchor navigation or pushState.
*/
diff --git a/docshell/shistory/nsSHEntry.cpp b/docshell/shistory/nsSHEntry.cpp
index e39b5888c157..27f21a23d2ba 100644
--- a/docshell/shistory/nsSHEntry.cpp
+++ b/docshell/shistory/nsSHEntry.cpp
@@ -42,7 +42,8 @@ nsSHEntry::nsSHEntry()
mIsSrcdocEntry(false),
mScrollRestorationIsManual(false),
mLoadedInThisProcess(false),
- mPersist(true) {}
+ mPersist(true),
+ mAllowOnionUrlbarRewrites(false) {}
nsSHEntry::nsSHEntry(const nsSHEntry& aOther)
: mShared(aOther.mShared),
@@ -68,7 +69,8 @@ nsSHEntry::nsSHEntry(const nsSHEntry& aOther)
mIsSrcdocEntry(aOther.mIsSrcdocEntry),
mScrollRestorationIsManual(false),
mLoadedInThisProcess(aOther.mLoadedInThisProcess),
- mPersist(aOther.mPersist) {}
+ mPersist(aOther.mPersist),
+ mAllowOnionUrlbarRewrites(aOther.mAllowOnionUrlbarRewrites) {}
nsSHEntry::~nsSHEntry() {
// Null out the mParent pointers on all our kids.
@@ -855,3 +857,15 @@ nsSHEntry::SetPersist(bool aPersist) {
mPersist = aPersist;
return NS_OK;
}
+
+NS_IMETHODIMP
+nsSHEntry::GetAllowOnionUrlbarRewrites(bool* aAllowOnionUrlbarRewrites) {
+ *aAllowOnionUrlbarRewrites = mAllowOnionUrlbarRewrites;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsSHEntry::SetAllowOnionUrlbarRewrites(bool aAllowOnionUrlbarRewrites) {
+ mAllowOnionUrlbarRewrites = aAllowOnionUrlbarRewrites;
+ return NS_OK;
+}
diff --git a/docshell/shistory/nsSHEntry.h b/docshell/shistory/nsSHEntry.h
index 4a9d7e466b22..aeb42b307739 100644
--- a/docshell/shistory/nsSHEntry.h
+++ b/docshell/shistory/nsSHEntry.h
@@ -61,6 +61,7 @@ class nsSHEntry final : public nsISHEntry {
bool mScrollRestorationIsManual;
bool mLoadedInThisProcess;
bool mPersist;
+ bool mAllowOnionUrlbarRewrites;
};
#endif /* nsSHEntry_h */
diff --git a/modules/libpref/init/StaticPrefList.h b/modules/libpref/init/StaticPrefList.h
index 47f4626f7e6b..29732ac3e884 100644
--- a/modules/libpref/init/StaticPrefList.h
+++ b/modules/libpref/init/StaticPrefList.h
@@ -2650,6 +2650,13 @@ VARCACHE_PREF(
bool, false
)
+// Whether rewriting the urlbar to a short .onion alias is allowed.
+VARCACHE_PREF(
+ "browser.urlbar.onionRewrites.enabled",
+ browser_urlbar_onionRewrites_enabled,
+ bool, true
+)
+
//---------------------------------------------------------------------------
// ChannelClassifier prefs
//---------------------------------------------------------------------------
diff --git a/netwerk/dns/effective_tld_names.dat b/netwerk/dns/effective_tld_names.dat
index 70e198aa3712..0c53819d860d 100644
--- a/netwerk/dns/effective_tld_names.dat
+++ b/netwerk/dns/effective_tld_names.dat
@@ -5495,6 +5495,8 @@ pro.om
// onion : https://tools.ietf.org/html/rfc7686
onion
+tor.onion
+securedrop.tor.onion
// org : https://en.wikipedia.org/wiki/.org
org
diff --git a/toolkit/components/remotebrowserutils/RemoteWebNavigation.jsm b/toolkit/components/remotebrowserutils/RemoteWebNavigation.jsm
index 6d971c10180a..76ce03dc6897 100644
--- a/toolkit/components/remotebrowserutils/RemoteWebNavigation.jsm
+++ b/toolkit/components/remotebrowserutils/RemoteWebNavigation.jsm
@@ -60,6 +60,7 @@ RemoteWebNavigation.prototype = {
LOAD_FLAGS_ALLOW_POPUPS: 32768,
LOAD_FLAGS_BYPASS_CLASSIFIER: 65536,
LOAD_FLAGS_FORCE_ALLOW_COOKIES: 131072,
+ LOAD_FLAGS_ALLOW_ONION_URLBAR_REWRITES: 16777216,
STOP_NETWORK: 1,
STOP_CONTENT: 2,
diff --git a/toolkit/content/widgets/browser-custom-element.js b/toolkit/content/widgets/browser-custom-element.js
index f31058012cbb..d26c8f8f0d1d 100644
--- a/toolkit/content/widgets/browser-custom-element.js
+++ b/toolkit/content/widgets/browser-custom-element.js
@@ -283,6 +283,8 @@
this._mayEnableCharacterEncodingMenu = null;
+ this._allowOnionUrlbarRewrites = false;
+
this._contentPrincipal = null;
this._csp = null;
@@ -677,6 +679,12 @@
: this.docShell.mayEnableCharacterEncodingMenu;
}
+ get allowOnionUrlbarRewrites() {
+ return this.isRemoteBrowser
+ ? this._allowOnionUrlbarRewrites
+ : this.docShell.allowOnionUrlbarRewrites;
+ }
+
get contentPrincipal() {
return this.isRemoteBrowser
? this._contentPrincipal
@@ -1870,6 +1878,7 @@
"_textZoom",
"_isSyntheticDocument",
"_innerWindowID",
+ "_allowOnionUrlbarRewrites",
]
);
}
diff --git a/toolkit/modules/RemoteWebProgress.jsm b/toolkit/modules/RemoteWebProgress.jsm
index 0f3c53a17a8c..558c31515570 100644
--- a/toolkit/modules/RemoteWebProgress.jsm
+++ b/toolkit/modules/RemoteWebProgress.jsm
@@ -281,6 +281,8 @@ class RemoteWebProgressManager {
this._browser._isSyntheticDocument = json.synthetic;
this._browser._innerWindowID = json.innerWindowID;
this._browser._contentRequestContextID = json.requestContextID;
+ this._browser._allowOnionUrlbarRewrites =
+ json.allowOnionUrlbarRewrites;
}
this.onLocationChange(webProgress, request, location, flags);
diff --git a/toolkit/modules/WebProgressChild.jsm b/toolkit/modules/WebProgressChild.jsm
index 60a1aa88e8ef..26250e361bd4 100644
--- a/toolkit/modules/WebProgressChild.jsm
+++ b/toolkit/modules/WebProgressChild.jsm
@@ -167,6 +167,7 @@ class WebProgressChild {
json.requestContextID = this.mm.content.document.documentLoadGroup
? this.mm.content.document.documentLoadGroup.requestContextID
: null;
+ json.allowOnionUrlbarRewrites = this.mm.docShell.allowOnionUrlbarRewrites;
if (AppConstants.MOZ_CRASHREPORTER && CrashReporter.enabled) {
let uri = aLocationURI;
diff --git a/toolkit/modules/sessionstore/SessionHistory.jsm b/toolkit/modules/sessionstore/SessionHistory.jsm
index e54ab3369cd8..463f147a9ca4 100644
--- a/toolkit/modules/sessionstore/SessionHistory.jsm
+++ b/toolkit/modules/sessionstore/SessionHistory.jsm
@@ -287,6 +287,7 @@ var SessionHistoryInternal = {
}
entry.persist = shEntry.persist;
+ entry.allowOnionUrlbarRewrites = shEntry.allowOnionUrlbarRewrites;
return entry;
},
@@ -559,6 +560,10 @@ var SessionHistoryInternal = {
}
}
+ if (entry.allowOnionUrlbarRewrites) {
+ shEntry.allowOnionUrlbarRewrites = entry.allowOnionUrlbarRewrites;
+ }
+
return shEntry;
},
1
0
[tor-browser/tor-browser-68.6.0esr-9.5-1] Merge commit 'da5513527e50e7f13e3b1c3206ed75ff8fbd76db' into tor-browser-68.6.0esr-9.5-1
by sysrqb@torproject.org 03 Apr '20
by sysrqb@torproject.org 03 Apr '20
03 Apr '20
commit 2d2c850302274bdf1a506949856c91c5b138983c
Merge: 31200493ae90 da5513527e50
Author: Matthew Finkel <sysrqb(a)torproject.org>
Date: Fri Apr 3 02:13:56 2020 +0000
Merge commit 'da5513527e50e7f13e3b1c3206ed75ff8fbd76db' into tor-browser-68.6.0esr-9.5-1
browser/base/content/browser.js | 12 ++
browser/base/content/browser.xul | 3 +
browser/components/BrowserGlue.jsm | 10 ++
.../onionservices/OnionLocationChild.jsm | 43 ++++++
.../onionservices/OnionLocationParent.jsm | 161 +++++++++++++++++++++
.../content/onionlocation-notification-icons.css | 5 +
.../onionservices/content/onionlocation-urlbar.css | 27 ++++
.../content/onionlocation-urlbar.inc.xul | 10 ++
.../onionservices/content/onionlocation.svg | 3 +
.../content/onionlocationPreferences.inc.xul | 11 ++
.../content/onionlocationPreferences.js | 31 ++++
browser/components/onionservices/jar.mn | 2 +
browser/components/onionservices/moz.build | 2 +
.../components/preferences/in-content/privacy.js | 17 +++
.../components/preferences/in-content/privacy.xul | 2 +
browser/modules/TorStrings.jsm | 39 +++++
browser/themes/shared/notification-icons.inc.css | 2 +
browser/themes/shared/urlbar-searchbar.inc.css | 2 +
dom/base/Document.cpp | 32 +++-
dom/base/Document.h | 2 +
dom/webidl/Document.webidl | 9 ++
modules/libpref/init/StaticPrefList.h | 7 +
xpcom/ds/StaticAtoms.py | 1 +
23 files changed, 432 insertions(+), 1 deletion(-)
diff --cc browser/components/onionservices/moz.build
index e4b6d73f8f40,bf276c4a3c4c..dfd664df434e
--- a/browser/components/onionservices/moz.build
+++ b/browser/components/onionservices/moz.build
@@@ -1,7 -1,6 +1,9 @@@
JAR_MANIFESTS += ['jar.mn']
EXTRA_JS_MODULES += [
+ 'ExtensionMessaging.jsm',
+ 'HttpsEverywhereControl.jsm',
+ 'OnionAliasStore.jsm',
+ 'OnionLocationChild.jsm',
+ 'OnionLocationParent.jsm',
]
1
0
[tor-browser/tor-browser-68.6.0esr-9.5-1] fixup! Pick up latest Torbutton code
by sysrqb@torproject.org 03 Apr '20
by sysrqb@torproject.org 03 Apr '20
03 Apr '20
commit 51cf695dd401dc0ce322c32145b207e13904ce65
Author: Matthew Finkel <sysrqb(a)torproject.org>
Date: Fri Apr 3 02:21:53 2020 +0000
fixup! Pick up latest Torbutton code
---
toolkit/torproject/torbutton | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/toolkit/torproject/torbutton b/toolkit/torproject/torbutton
index ce150c56c02a..dd027529aecd 160000
--- a/toolkit/torproject/torbutton
+++ b/toolkit/torproject/torbutton
@@ -1 +1 @@
-Subproject commit ce150c56c02a3bd48b345d104132b9d4868bd174
+Subproject commit dd027529aecd4f6632c41b2f07bd6519b0e4cbf5
1
0
03 Apr '20
commit 8026b5ea1bff17c30a95df2192b475e569501a2d
Author: Alex Catarineu <acat(a)torproject.org>
Date: Tue Mar 10 19:13:37 2020 +0100
Bug 21952: Add strings for Onion-Location
---
chrome/locale/en-US/torbutton.properties | 14 ++++++++++++++
1 file changed, 14 insertions(+)
diff --git a/chrome/locale/en-US/torbutton.properties b/chrome/locale/en-US/torbutton.properties
index 375067b3..49c72194 100644
--- a/chrome/locale/en-US/torbutton.properties
+++ b/chrome/locale/en-US/torbutton.properties
@@ -80,3 +80,17 @@ onionServices.authPreferences.remove=Remove
onionServices.authPreferences.removeAll=Remove All
onionServices.authPreferences.failedToGetKeys=Unable to retrieve keys from tor
onionServices.authPreferences.failedToRemoveKey=Unable to remove key
+
+# Onion-Location strings.
+onionLocation.alwaysPrioritize=Always Prioritize Onions
+onionLocation.alwaysPrioritizeAccessKey=a
+onionLocation.notNow=Not Now
+onionLocation.notNowAccessKey=n
+onionLocation.description=There's a more private and secure version of this site available over the Tor network via onion services. Onion services help website publishers and their visitors defeat surveillance and censorship.
+onionLocation.tryThis=Try Onion Services
+onionLocation.onionAvailable=.onion available
+onionLocation.learnMore=Learn more…
+onionLocation.always=Always
+onionLocation.askEverytime=Ask every time
+onionLocation.prioritizeOnionsDescription=Prioritize .onion sites when known.
+onionLocation.onionServicesTitle=Onion Services
1
0
[torbutton/master] Merge remote-tracking branch 'bradetpo/bug19251-03'
by sysrqb@torproject.org 03 Apr '20
by sysrqb@torproject.org 03 Apr '20
03 Apr '20
commit 751a8d02b6ca5e7c8e2a05972c83f2776996f3d8
Merge: d2ca013e 7ce7e376
Author: Matthew Finkel <sysrqb(a)torproject.org>
Date: Fri Apr 3 01:57:57 2020 +0000
Merge remote-tracking branch 'bradetpo/bug19251-03'
chrome/locale/en-US/torbutton.properties | 49 ++++++++++++++++++++++++++++++--
1 file changed, 47 insertions(+), 2 deletions(-)
1
0
[torbutton/master] Bug 28005: Crop long .onion domains in circuit display and implement click to copy
by sysrqb@torproject.org 03 Apr '20
by sysrqb@torproject.org 03 Apr '20
03 Apr '20
commit e6fb19bf14512707f1141a1306f9ee11dadcd2f6
Author: Alex Catarineu <acat(a)torproject.org>
Date: Mon Feb 10 16:04:44 2020 +0100
Bug 28005: Crop long .onion domains in circuit display and implement click to copy
We also show a tooltip with the full domain on hover, so that it's not
necessary to copy it for users to see it.
---
chrome/content/tor-circuit-display.js | 34 ++++++++++++++++++++++++++++++--
chrome/locale/en-US/torbutton.properties | 2 ++
chrome/skin/tor-circuit-display.css | 26 ++++++++++++++++++++++++
3 files changed, 60 insertions(+), 2 deletions(-)
diff --git a/chrome/content/tor-circuit-display.js b/chrome/content/tor-circuit-display.js
index 19b55d18..119f6fca 100644
--- a/chrome/content/tor-circuit-display.js
+++ b/chrome/content/tor-circuit-display.js
@@ -236,7 +236,9 @@ let showCircuitDisplay = function (show) {
// and returns nested xml element objects.
let xmlTree = function xmlTree (ns, data) {
let [type, attrs, ...children] = data;
- let element = document.createElementNS(ns, type);
+ let element = type.startsWith("html:")
+ ? document.createXULElement(type)
+ : document.createElementNS(ns, type);
for (let [key, val] of Object.entries(attrs)) {
element.setAttribute(key, val);
}
@@ -308,12 +310,40 @@ let updateCircuitDisplay = function () {
(i === 0 && nodeData[0].type !== "bridge") ?
["span", { class: "circuit-guard-info" }, uiString("guard")] : null);
}
+
+ let domainParts = [];
if (domain.endsWith(".onion")) {
for (let i = 0; i < 3; ++i) {
li(uiString("relay"));
}
+ if (domain.length > 22) {
+ domainParts.push(domain.slice(0, 7), "…", domain.slice(-12));
+ } else {
+ domainParts.push(domain);
+ }
+ } else {
+ domainParts.push(domain);
}
- li(domain);
+
+ // We use a XUL html:span element so that the tooltiptext is displayed.
+ li([
+ "html:span",
+ {
+ class: "circuit-onion",
+ onclick: `
+ this.classList.add("circuit-onion-copied");
+ Cc[
+ "@mozilla.org/widget/clipboardhelper;1"
+ ].getService(Ci.nsIClipboardHelper).copyString(this.getAttribute("data-onion"))
+ `,
+ "data-onion": domain,
+ "data-text-clicktocopy": torbutton_get_property_string("torbutton.circuit_display.click_to_copy"),
+ "data-text-copied": torbutton_get_property_string("torbutton.circuit_display.copied"),
+ tooltiptext: domain,
+ },
+ ...domainParts,
+ ]);
+
// Hide the note about guards if we are using a bridge.
document.getElementById("circuit-guard-note-container").style.display =
(nodeData[0].type === "bridge") ? "none" : "block";
diff --git a/chrome/locale/en-US/torbutton.properties b/chrome/locale/en-US/torbutton.properties
index 375067b3..14330f6f 100644
--- a/chrome/locale/en-US/torbutton.properties
+++ b/chrome/locale/en-US/torbutton.properties
@@ -8,6 +8,8 @@ torbutton.circuit_display.unknown_country = Unknown country
torbutton.circuit_display.guard = Guard
torbutton.circuit_display.guard_note = Your [Guard] node may not change.
torbutton.circuit_display.learn_more = Learn more
+torbutton.circuit_display.click_to_copy = Click to Copy
+torbutton.circuit_display.copied = Copied!
torbutton.content_sizer.margin_tooltip = Tor Browser adds this margin to make the width and height of your window less distinctive, and thus reduces the ability of people to track you online.
torbutton.panel.tooltip.disabled = Click to enable Tor
torbutton.panel.tooltip.enabled = Click to disable Tor
diff --git a/chrome/skin/tor-circuit-display.css b/chrome/skin/tor-circuit-display.css
index 485ae7a5..3c349e0c 100644
--- a/chrome/skin/tor-circuit-display.css
+++ b/chrome/skin/tor-circuit-display.css
@@ -155,3 +155,29 @@ ul#circuit-display-nodes li:last-child {
.circuit-link:hover {
text-decoration: underline;
}
+
+.circuit-onion {
+ cursor: pointer;
+}
+
+.circuit-onion:hover::after {
+ opacity: 1;
+}
+
+.circuit-onion::after {
+ background-color: #e3e3e3;
+ border-radius: 2px;
+ color: black;
+ content: attr(data-text-clicktocopy);
+ font-size: 80%;
+ opacity: 0;
+ padding: 5px;
+ margin: 10px;
+ text-align: center;
+ transition: opacity 0.3s cubic-bezier(0.07, 0.95, 0, 1);
+}
+
+.circuit-onion-copied::after {
+ content: attr(data-text-copied);
+ opacity: 1;
+}
1
0
03 Apr '20
commit b2d4c6348cb7cc604ef705b04837baf5db59041f
Merge: 751a8d02 e6fb19bf
Author: Matthew Finkel <sysrqb(a)torproject.org>
Date: Fri Apr 3 02:16:11 2020 +0000
Merge remote-tracking branch 'acat/28005+2'
chrome/content/tor-circuit-display.js | 34 ++++++++++++++++++++++++++++++--
chrome/locale/en-US/torbutton.properties | 2 ++
chrome/skin/tor-circuit-display.css | 26 ++++++++++++++++++++++++
3 files changed, 60 insertions(+), 2 deletions(-)
1
0
[torbutton/master] Bug 19251: Show improved error pages for onion service errors.
by sysrqb@torproject.org 03 Apr '20
by sysrqb@torproject.org 03 Apr '20
03 Apr '20
commit 7ce7e376fc8f3e51cf5de04f1a254c9190e3364b
Author: Kathy Brade <brade(a)pearlcrescent.com>
Date: Wed Mar 4 16:49:14 2020 -0500
Bug 19251: Show improved error pages for onion service errors.
Add strings for onion service error pages.
---
chrome/locale/en-US/torbutton.properties | 49 ++++++++++++++++++++++++++++++--
1 file changed, 47 insertions(+), 2 deletions(-)
diff --git a/chrome/locale/en-US/torbutton.properties b/chrome/locale/en-US/torbutton.properties
index 375067b3..536c3ade 100644
--- a/chrome/locale/en-US/torbutton.properties
+++ b/chrome/locale/en-US/torbutton.properties
@@ -60,9 +60,54 @@ pageInfo_OnionEncryptionWithBitsAndProtocol=Connection Encrypted (Onion Service,
pageInfo_OnionEncryption=Connection Encrypted (Onion Service)
# Onion services strings. Strings are kept here for ease of translation.
-# LOCALIZATION NOTE: %S will be replaced with the .onion address.
onionServices.learnMore=Learn more
-onionServices.clientAuthMissing=Tor onion service missing client authorization
+onionServices.errorPage.browser=Browser
+onionServices.errorPage.network=Network
+onionServices.errorPage.onionSite=Onionsite
+# LOCALIZATION NOTE: In the longDescription strings, %S will be replaced with
+# an error code, e.g., 0xF3.
+# Tor SOCKS error 0xF0:
+onionServices.descNotFound.pageTitle=Problem Loading Onionsite
+onionServices.descNotFound.header=Onionsite Not Found
+onionServices.descNotFound=The most likely cause is that the onionsite is offline. Contact the onionsite administrator.
+onionServices.descNotFound.longDescription=Details: %S — The requested onion service descriptor can't be found on the hashring and therefore the service is not reachable by the client.
+# Tor SOCKS error 0xF1:
+onionServices.descInvalid.pageTitle=Problem Loading Onionsite
+onionServices.descInvalid.header=Onionsite Cannot Be Reached
+onionServices.descInvalid=The onionsite is unreachable due an internal error.
+onionServices.descInvalid.longDescription=Details: %S — The requested onion service descriptor can't be parsed or signature validation failed.
+# Tor SOCKS error 0xF2:
+onionServices.introFailed.pageTitle=Problem Loading Onionsite
+onionServices.introFailed.header=Onionsite Has Disconnected
+onionServices.introFailed=The most likely cause is that the onionsite is offline. Contact the onionsite administrator.
+onionServices.introFailed.longDescription=Details: %S — Introduction failed, which means that the descriptor was found but the service is no longer connected to the introduction point. It is likely that the service has changed its descriptor or that it is not running.
+# Tor SOCKS error 0xF3:
+onionServices.rendezvousFailed.pageTitle=Problem Loading Onionsite
+onionServices.rendezvousFailed.header=Unable to Connect to Onionsite
+onionServices.rendezvousFailed=The onionsite is busy or the Tor network is overloaded. Try again later.
+onionServices.rendezvousFailed.longDescription=Details: %S — The client failed to rendezvous with the service, which means that the client was unable to finalize the connection.
+# Tor SOCKS error 0xF4:
+onionServices.clientAuthMissing.pageTitle=Authorization Required
+onionServices.clientAuthMissing.header=Onionsite Requires Authentication
+onionServices.clientAuthMissing=Access to the onionsite requires a key but none was provided.
+onionServices.clientAuthMissing.longDescription=Details: %S — The client downloaded the requested onion service descriptor but was unable to decrypt its content because client authorization information is missing.
+# Tor SOCKS error 0xF5:
+onionServices.clientAuthIncorrect.pageTitle=Authorization Failed
+onionServices.clientAuthIncorrect.header=Onionsite Authentication Failed
+onionServices.clientAuthIncorrect=The provided key is incorrect or has been revoked. Contact the onionsite administrator.
+onionServices.clientAuthIncorrect.longDescription=Details: %S — The client was able to download the requested onion service descriptor but was unable to decrypt its content using the provided client authorization information. This may mean that access has been revoked.
+# Tor SOCKS error 0xF6:
+onionServices.badAddress.pageTitle=Problem Loading Onionsite
+onionServices.badAddress.header=Invalid Onionsite Address
+onionServices.badAddress=The provided onionsite address is invalid. Please check that you entered it correctly.
+onionServices.badAddress.longDescription=Details: %S — The provided .onion address is invalid. This error is returned due to one of the following reasons: the address checksum doesn't match, the ed25519 public key is invalid, or the encoding is invalid.
+# Tor SOCKS error 0xF7:
+onionServices.introTimedOut.pageTitle=Problem Loading Onionsite
+onionServices.introTimedOut.header=Onionsite Circuit Creation Timed Out
+onionServices.introTimedOut=Failed to connect to the onionsite, possibly due to a poor network connection.
+onionServices.introTimedOut.longDescription=Details: %S — The connection to the requested onion service timed out while trying to build the rendezvous circuit.
+#
+# LOCALIZATION NOTE: %S will be replaced with the .onion address.
onionServices.authPrompt.description=%S is requesting your private key.
onionServices.authPrompt.keyPlaceholder=Enter your private key for this onion service
onionServices.authPrompt.done=Done
1
0