tor-commits
Threads by month
- ----- 2025 -----
- 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
June 2021
- 17 participants
- 1287 discussions

[tor-browser/tor-browser-78.11.0esr-10.5-1] Bug 24796 - Comment out excess permissions from GeckoView
by sysrqb@torproject.org 02 Jun '21
by sysrqb@torproject.org 02 Jun '21
02 Jun '21
commit 849c2e5fe2b33881a5abfc75130495b5f716aa9a
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.11.0esr-10.5-1] Bug 32658: Create a new MAR signing key
by sysrqb@torproject.org 02 Jun '21
by sysrqb@torproject.org 02 Jun '21
02 Jun '21
commit 0df0b5737de2fd2918cf4c57ce983a85e9db158c
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.11.0esr-10.5-1] Bug 25741 - TBA: Disable GeckoNetworkManager
by sysrqb@torproject.org 02 Jun '21
by sysrqb@torproject.org 02 Jun '21
02 Jun '21
commit 480960b262e627e57619b0046545e741f434fca7
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.11.0esr-10.5-1] Bug 28125 - Prevent non-Necko network connections
by sysrqb@torproject.org 02 Jun '21
by sysrqb@torproject.org 02 Jun '21
02 Jun '21
commit b87b5434168c41c29c02a56048365b72b66d38d0
Author: Matthew Finkel <Matthew.Finkel(a)gmail.com>
Date: Thu Oct 25 19:17:09 2018 +0000
Bug 28125 - Prevent non-Necko network connections
---
.../gecko/media/GeckoMediaDrmBridgeV21.java | 49 +---------------------
.../exoplayer2/upstream/DefaultHttpDataSource.java | 47 +--------------------
2 files changed, 3 insertions(+), 93 deletions(-)
diff --git a/mobile/android/geckoview/src/main/java/org/mozilla/gecko/media/GeckoMediaDrmBridgeV21.java b/mobile/android/geckoview/src/main/java/org/mozilla/gecko/media/GeckoMediaDrmBridgeV21.java
index 3ba59bfd6776..eb57b1013642 100644
--- a/mobile/android/geckoview/src/main/java/org/mozilla/gecko/media/GeckoMediaDrmBridgeV21.java
+++ b/mobile/android/geckoview/src/main/java/org/mozilla/gecko/media/GeckoMediaDrmBridgeV21.java
@@ -488,54 +488,7 @@ public class GeckoMediaDrmBridgeV21 implements GeckoMediaDrm {
@Override
protected Void doInBackground(final Void... params) {
- HttpURLConnection urlConnection = null;
- BufferedReader in = null;
- try {
- URI finalURI = new URI(mURL + "&signedRequest=" + URLEncoder.encode(new String(mDrmRequest), "UTF-8"));
- urlConnection = (HttpURLConnection) ProxySelector.openConnectionWithProxy(finalURI);
- urlConnection.setRequestMethod("POST");
- if (DEBUG) Log.d(LOGTAG, "Provisioning, posting url =" + finalURI.toString());
-
- // Add data
- urlConnection.setRequestProperty("Accept", "*/*");
- urlConnection.setRequestProperty("User-Agent", getCDMUserAgent());
- urlConnection.setRequestProperty("Content-Type", "application/json");
-
- // Execute HTTP Post Request
- urlConnection.connect();
-
- int responseCode = urlConnection.getResponseCode();
- if (responseCode == HttpURLConnection.HTTP_OK) {
- in = new BufferedReader(new InputStreamReader(urlConnection.getInputStream(), StringUtils.UTF_8));
- String inputLine;
- StringBuffer response = new StringBuffer();
-
- while ((inputLine = in.readLine()) != null) {
- response.append(inputLine);
- }
- in.close();
- mResponseBody = String.valueOf(response).getBytes(StringUtils.UTF_8);
- if (DEBUG) Log.d(LOGTAG, "Provisioning, response received.");
- if (mResponseBody != null) Log.d(LOGTAG, "response length=" + mResponseBody.length);
- } else {
- Log.d(LOGTAG, "Provisioning, server returned HTTP error code :" + responseCode);
- }
- } catch (IOException e) {
- Log.e(LOGTAG, "Got exception during posting provisioning request ...", e);
- } catch (URISyntaxException e) {
- Log.e(LOGTAG, "Got exception during creating uri ...", e);
- } finally {
- if (urlConnection != null) {
- urlConnection.disconnect();
- }
- try {
- if (in != null) {
- in.close();
- }
- } catch (IOException e) {
- Log.e(LOGTAG, "Exception during closing in ...", e);
- }
- }
+ Log.i(LOGTAG, "This is Tor Browser. Skipping.");
return null;
}
diff --git a/mobile/android/geckoview/src/thirdparty/java/org/mozilla/thirdparty/com/google/android/exoplayer2/upstream/DefaultHttpDataSource.java b/mobile/android/geckoview/src/thirdparty/java/org/mozilla/thirdparty/com/google/android/exoplayer2/upstream/DefaultHttpDataSource.java
index fdb44cc2ea1f..7a2044721d2d 100644
--- a/mobile/android/geckoview/src/thirdparty/java/org/mozilla/thirdparty/com/google/android/exoplayer2/upstream/DefaultHttpDataSource.java
+++ b/mobile/android/geckoview/src/thirdparty/java/org/mozilla/thirdparty/com/google/android/exoplayer2/upstream/DefaultHttpDataSource.java
@@ -395,51 +395,8 @@ public class DefaultHttpDataSource implements HttpDataSource {
*/
private HttpURLConnection makeConnection(URL url, byte[] postBody, long position,
long length, boolean allowGzip, boolean followRedirects) throws IOException, URISyntaxException {
- /**
- * Tor Project modified the way the connection object was created. For the sake of
- * simplicity, instead of duplicating the whole file we changed the connection object
- * to use the ProxySelector.
- */
- HttpURLConnection connection = (HttpURLConnection) ProxySelector.openConnectionWithProxy(url.toURI());
-
- connection.setConnectTimeout(connectTimeoutMillis);
- connection.setReadTimeout(readTimeoutMillis);
- if (defaultRequestProperties != null) {
- for (Map.Entry<String, String> property : defaultRequestProperties.getSnapshot().entrySet()) {
- connection.setRequestProperty(property.getKey(), property.getValue());
- }
- }
- for (Map.Entry<String, String> property : requestProperties.getSnapshot().entrySet()) {
- connection.setRequestProperty(property.getKey(), property.getValue());
- }
- if (!(position == 0 && length == C.LENGTH_UNSET)) {
- String rangeRequest = "bytes=" + position + "-";
- if (length != C.LENGTH_UNSET) {
- rangeRequest += (position + length - 1);
- }
- connection.setRequestProperty("Range", rangeRequest);
- }
- connection.setRequestProperty("User-Agent", userAgent);
- if (!allowGzip) {
- connection.setRequestProperty("Accept-Encoding", "identity");
- }
- connection.setInstanceFollowRedirects(followRedirects);
- connection.setDoOutput(postBody != null);
- if (postBody != null) {
- connection.setRequestMethod("POST");
- if (postBody.length == 0) {
- connection.connect();
- } else {
- connection.setFixedLengthStreamingMode(postBody.length);
- connection.connect();
- OutputStream os = connection.getOutputStream();
- os.write(postBody);
- os.close();
- }
- } else {
- connection.connect();
- }
- return connection;
+ Log.i(TAG, "This is Tor Browser. Skipping.");
+ throw new IOException();
}
/**
1
0

[tor-browser/tor-browser-78.11.0esr-10.5-1] Bug 21952: Implement Onion-Location
by sysrqb@torproject.org 02 Jun '21
by sysrqb@torproject.org 02 Jun '21
02 Jun '21
commit 73c4812144370aed4f7c433cb8b049f39254c1cb
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.xhtml | 3 +
browser/components/BrowserGlue.jsm | 9 ++
.../onionservices/OnionLocationChild.jsm | 43 ++++++
.../onionservices/OnionLocationParent.jsm | 161 +++++++++++++++++++++
.../content/onionlocation-notification-icons.css | 5 +
.../onionservices/content/onionlocation-urlbar.css | 27 ++++
.../content/onionlocation-urlbar.inc.xhtml | 10 ++
.../onionservices/content/onionlocation.svg | 3 +
.../content/onionlocationPreferences.inc.xhtml | 11 ++
.../content/onionlocationPreferences.js | 31 ++++
browser/components/onionservices/jar.mn | 2 +
browser/components/onionservices/moz.build | 2 +
browser/components/preferences/privacy.inc.xhtml | 2 +
browser/components/preferences/privacy.js | 17 +++
browser/themes/shared/notification-icons.inc.css | 2 +
browser/themes/shared/urlbar-searchbar.inc.css | 2 +
dom/base/Document.cpp | 34 ++++-
dom/base/Document.h | 2 +
dom/webidl/Document.webidl | 9 ++
modules/libpref/init/StaticPrefList.yaml | 5 +
xpcom/ds/StaticAtoms.py | 1 +
22 files changed, 392 insertions(+), 1 deletion(-)
diff --git a/browser/base/content/browser.js b/browser/base/content/browser.js
index bd5f10cb6f64..04f8752b93f4 100644
--- a/browser/base/content/browser.js
+++ b/browser/base/content/browser.js
@@ -44,6 +44,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",
@@ -5422,6 +5423,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
@@ -5964,6 +5966,16 @@ const AccessibilityRefreshBlocker = {
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.xhtml b/browser/base/content/browser.xhtml
index 4cab5fad6475..c2caecc1a416 100644
--- a/browser/base/content/browser.xhtml
+++ b/browser/base/content/browser.xhtml
@@ -1077,6 +1077,9 @@
onclick="FullZoom.reset();"
tooltip="dynamic-shortcut-tooltip"
hidden="true"/>
+
+#include ../../components/onionservices/content/onionlocation-urlbar.inc.xhtml
+
<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 d30abff54562..e08e461a27ff 100644
--- a/browser/components/BrowserGlue.jsm
+++ b/browser/components/BrowserGlue.jsm
@@ -539,6 +539,13 @@ let LEGACY_ACTORS = {
observers: ["keyword-uri-fixup"],
},
},
+ OnionLocation: {
+ child: {
+ module: "resource:///modules/OnionLocationChild.jsm",
+ events: { pageshow: {} },
+ messages: ["OnionLocation:Refresh"],
+ },
+ },
};
if (AppConstants.TOR_BROWSER_UPDATE) {
@@ -713,6 +720,7 @@ XPCOMUtils.defineLazyModuleGetters(this, {
XPCOMUtils.defineLazyModuleGetters(this, {
AboutLoginsParent: "resource:///modules/AboutLoginsParent.jsm",
AsyncPrefs: "resource://gre/modules/AsyncPrefs.jsm",
+ OnionLocationParent: "resource:///modules/OnionLocationParent.jsm",
PluginManager: "resource:///actors/PluginParent.jsm",
ReaderParent: "resource:///modules/ReaderParent.jsm",
});
@@ -816,6 +824,7 @@ const listeners = {
"AboutLogins:VulnerableLogins": ["AboutLoginsParent"],
"Reader:FaviconRequest": ["ReaderParent"],
"Reader:UpdateReaderButton": ["ReaderParent"],
+ "OnionLocation:Set": ["OnionLocationParent"],
},
observe(subject, topic, data) {
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.xhtml b/browser/components/onionservices/content/onionlocation-urlbar.inc.xhtml
new file mode 100644
index 000000000000..b612a4236f3c
--- /dev/null
+++ b/browser/components/onionservices/content/onionlocation-urlbar.inc.xhtml
@@ -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.xhtml b/browser/components/onionservices/content/onionlocationPreferences.inc.xhtml
new file mode 100644
index 000000000000..c285f403f99b
--- /dev/null
+++ b/browser/components/onionservices/content/onionlocationPreferences.inc.xhtml
@@ -0,0 +1,11 @@
+# Copyright (c) 2020, The Tor Project, Inc.
+
+<groupbox id="onionServicesGroup" data-category="panePrivacy" data-subcategory="onionservices" hidden="true">
+ <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 9d6ce88d1841..f45b16dc5d29 100644
--- a/browser/components/onionservices/jar.mn
+++ b/browser/components/onionservices/jar.mn
@@ -7,3 +7,5 @@ browser.jar:
content/browser/onionservices/onionservices.css (content/onionservices.css)
content/browser/onionservices/savedKeysDialog.js (content/savedKeysDialog.js)
content/browser/onionservices/savedKeysDialog.xhtml (content/savedKeysDialog.xhtml)
+ 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 e4b6d73f8f40..dfd664df434e 100644
--- a/browser/components/onionservices/moz.build
+++ b/browser/components/onionservices/moz.build
@@ -4,4 +4,6 @@ EXTRA_JS_MODULES += [
'ExtensionMessaging.jsm',
'HttpsEverywhereControl.jsm',
'OnionAliasStore.jsm',
+ 'OnionLocationChild.jsm',
+ 'OnionLocationParent.jsm',
]
diff --git a/browser/components/preferences/privacy.inc.xhtml b/browser/components/preferences/privacy.inc.xhtml
index eb7587afa0e1..6e05405079bf 100644
--- a/browser/components/preferences/privacy.inc.xhtml
+++ b/browser/components/preferences/privacy.inc.xhtml
@@ -14,6 +14,8 @@
<html:h1 data-l10n-id="privacy-header"/>
</hbox>
+#include ../onionservices/content/onionlocationPreferences.inc.xhtml
+
<!-- Tracking / Content Blocking -->
<groupbox id="trackingGroup" data-category="panePrivacy" hidden="true" aria-describedby="contentBlockingDescription">
<label id="contentBlockingHeader"><html:h2 data-l10n-id="content-blocking-enhanced-tracking-protection"/></label>
diff --git a/browser/components/preferences/privacy.js b/browser/components/preferences/privacy.js
index 41dda96a14de..92f35dc78d12 100644
--- a/browser/components/preferences/privacy.js
+++ b/browser/components/preferences/privacy.js
@@ -90,6 +90,12 @@ XPCOMUtils.defineLazyScriptGetter(
"chrome://browser/content/securitylevel/securityLevel.js"
);
+XPCOMUtils.defineLazyScriptGetter(
+ this,
+ ["OnionLocationPreferences"],
+ "chrome://browser/content/onionservices/onionlocationPreferences.js"
+);
+
XPCOMUtils.defineLazyServiceGetter(
this,
"listManager",
@@ -158,6 +164,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" },
@@ -300,6 +309,13 @@ var gPrivacyPane = {
window.addEventListener("unload", unload);
},
+ /**
+ * Show the OnionLocation preferences UI
+ */
+ _initOnionLocation() {
+ OnionLocationPreferences.init();
+ },
+
/**
* Whether the prompt to restart Firefox should appear when changing the autostart pref.
*/
@@ -442,6 +458,7 @@ var gPrivacyPane = {
this._initTrackingProtectionExtensionControl();
OnionServicesAuthPreferences.init();
this._initSecurityLevel();
+ this._initOnionLocation();
Services.telemetry.setEventRecordingEnabled("pwmgr", true);
diff --git a/browser/themes/shared/notification-icons.inc.css b/browser/themes/shared/notification-icons.inc.css
index 979ae9482244..7aa92d51f4d6 100644
--- a/browser/themes/shared/notification-icons.inc.css
+++ b/browser/themes/shared/notification-icons.inc.css
@@ -415,3 +415,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 0b1f69342995..d3cc6bf7f024 100644
--- a/browser/themes/shared/urlbar-searchbar.inc.css
+++ b/browser/themes/shared/urlbar-searchbar.inc.css
@@ -824,3 +824,5 @@
.searchbar-search-button:hover:not([addengines=true]) > .searchbar-search-icon-overlay:-moz-locale-dir(rtl) {
margin-inline: -26px 20px;
}
+
+%include ../../components/onionservices/content/onionlocation-urlbar.css
diff --git a/dom/base/Document.cpp b/dom/base/Document.cpp
index 132c0ecbfdac..afc872569519 100644
--- a/dom/base/Document.cpp
+++ b/dom/base/Document.cpp
@@ -2542,6 +2542,7 @@ void Document::ResetToURI(nsIURI* aURI, nsILoadGroup* aLoadGroup,
// mDocumentURI.
mDocumentBaseURI = nullptr;
mChromeXHRDocBaseURI = nullptr;
+ mOnionLocationURI = nullptr;
// Check if the current document is the top-level DevTools document.
// For inner DevTools frames, mIsDevToolsDocument will be set when
@@ -6026,6 +6027,22 @@ void Document::GetHeaderData(nsAtom* aHeaderField, nsAString& aData) const {
}
}
+static bool IsValidOnionLocation(nsIURI* aDocumentURI,
+ nsIURI* aOnionLocationURI) {
+ bool isHttpish;
+ nsAutoCString host;
+ return aDocumentURI && aOnionLocationURI &&
+ NS_SUCCEEDED(aDocumentURI->SchemeIs("https", &isHttpish)) &&
+ isHttpish && NS_SUCCEEDED(aDocumentURI->GetAsciiHost(host)) &&
+ !StringEndsWith(host, NS_LITERAL_CSTRING(".onion")) &&
+ ((NS_SUCCEEDED(aOnionLocationURI->SchemeIs("http", &isHttpish)) &&
+ isHttpish) ||
+ (NS_SUCCEEDED(aOnionLocationURI->SchemeIs("https", &isHttpish)) &&
+ isHttpish)) &&
+ NS_SUCCEEDED(aOnionLocationURI->GetAsciiHost(host)) &&
+ StringEndsWith(host, NS_LITERAL_CSTRING(".onion"));
+}
+
void Document::SetHeaderData(nsAtom* aHeaderField, const nsAString& aData) {
if (!aHeaderField) {
NS_ERROR("null headerField");
@@ -6101,6 +6118,21 @@ void Document::SetHeaderData(nsAtom* aHeaderField, const nsAString& aData) {
aHeaderField == nsGkAtoms::handheldFriendly) {
mViewportType = Unknown;
}
+
+ 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_enabled()) {
+ nsCOMPtr<nsIRefreshURI> refresher(mDocumentContainer);
+ if (refresher) {
+ refresher->RefreshURI(onionURI, NodePrincipal(), 0, false, true);
+ }
+ } else {
+ mOnionLocationURI = onionURI;
+ }
+ }
+ }
}
void Document::TryChannelCharset(nsIChannel* aChannel, int32_t& aCharsetSource,
@@ -10141,7 +10173,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",
+ "x-frame-options", "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 6d06a8c2a8cd..6e80306e94b5 100644
--- a/dom/base/Document.h
+++ b/dom/base/Document.h
@@ -3322,6 +3322,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
const char* GetFullscreenError(CallerType);
bool FullscreenEnabled(CallerType aCallerType) {
@@ -4194,6 +4195,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 8130db018f47..df3a18eaf266 100644
--- a/dom/webidl/Document.webidl
+++ b/dom/webidl/Document.webidl
@@ -676,3 +676,12 @@ partial interface Document {
[ChromeOnly, Pure]
readonly attribute nsIPermissionDelegateHandler permDelegateHandler;
};
+
+
+/**
+ * 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.yaml b/modules/libpref/init/StaticPrefList.yaml
index f1f2ccdf0cce..04d7575ab234 100644
--- a/modules/libpref/init/StaticPrefList.yaml
+++ b/modules/libpref/init/StaticPrefList.yaml
@@ -8446,6 +8446,11 @@
value: @IS_NIGHTLY_BUILD@
mirror: always
+- name: privacy.prioritizeonions.enabled
+ type: RelaxedAtomicBool
+ value: false
+ mirror: always
+
#---------------------------------------------------------------------------
# Prefs starting with "prompts."
#---------------------------------------------------------------------------
diff --git a/xpcom/ds/StaticAtoms.py b/xpcom/ds/StaticAtoms.py
index ab5f662575e4..23a5d6f9bb95 100644
--- a/xpcom/ds/StaticAtoms.py
+++ b/xpcom/ds/StaticAtoms.py
@@ -811,6 +811,7 @@ STATIC_ATOMS = [
Atom("oninputsourceschange","oninputsourceschange"),
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-78.11.0esr-10.5-1] Bug 32418: Allow updates to be disabled via an enterprise policy.
by sysrqb@torproject.org 02 Jun '21
by sysrqb@torproject.org 02 Jun '21
02 Jun '21
commit 96144981ba3ebd930a2986a5d53d109f318161a0
Author: Kathy Brade <brade(a)pearlcrescent.com>
Date: Thu Apr 16 17:07:09 2020 -0400
Bug 32418: Allow updates to be disabled via an enterprise policy.
Restrict the Enterprise Policies mechanism to only consult a
policies.json file (avoiding the Windows Registry and macOS's
file system attributes).
Add a few disabledByPolicy() checks to the update service to
avoid extraneous (and potentially confusing) log messages when
updates are disabled by policy.
Sample content for distribution/policies.json:
{
"policies": {
"DisableAppUpdate": true
}
}
On Linux, avoid reading policies from /etc/firefox/policies/policies.json
---
.../components/enterprisepolicies/EnterprisePolicies.js | 12 ++++++++++++
toolkit/components/enterprisepolicies/moz.build | 4 +++-
toolkit/mozapps/update/UpdateService.jsm | 16 ++++++++++++++++
3 files changed, 31 insertions(+), 1 deletion(-)
diff --git a/toolkit/components/enterprisepolicies/EnterprisePolicies.js b/toolkit/components/enterprisepolicies/EnterprisePolicies.js
index 070d5fe1f16b..adb073a2350c 100644
--- a/toolkit/components/enterprisepolicies/EnterprisePolicies.js
+++ b/toolkit/components/enterprisepolicies/EnterprisePolicies.js
@@ -2,6 +2,10 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+// To ensure that policies intended for Firefox or another browser will not
+// be used, Tor Browser only looks for policies in ${InstallDir}/distribution
+#define AVOID_SYSTEM_POLICIES MOZ_PROXY_BYPASS_PROTECTION
+
const { XPCOMUtils } = ChromeUtils.import(
"resource://gre/modules/XPCOMUtils.jsm"
);
@@ -11,9 +15,11 @@ const { AppConstants } = ChromeUtils.import(
);
XPCOMUtils.defineLazyModuleGetters(this, {
+#ifndef AVOID_SYSTEM_POLICIES
WindowsGPOParser: "resource://gre/modules/policies/WindowsGPOParser.jsm",
macOSPoliciesParser:
"resource://gre/modules/policies/macOSPoliciesParser.jsm",
+#endif
Policies: "resource:///modules/policies/Policies.jsm",
JsonSchemaValidator:
"resource://gre/modules/components-utils/JsonSchemaValidator.jsm",
@@ -117,11 +123,13 @@ EnterprisePoliciesManager.prototype = {
_chooseProvider() {
let platformProvider = null;
+#ifndef AVOID_SYSTEM_POLICIES
if (AppConstants.platform == "win") {
platformProvider = new WindowsGPOPoliciesProvider();
} else if (AppConstants.platform == "macosx") {
platformProvider = new macOSPoliciesProvider();
}
+#endif
let jsonProvider = new JSONPoliciesProvider();
if (platformProvider && platformProvider.hasPolicies) {
if (jsonProvider.hasPolicies) {
@@ -470,6 +478,7 @@ class JSONPoliciesProvider {
_getConfigurationFile() {
let configFile = null;
+#ifndef AVOID_SYSTEM_POLICIES
if (AppConstants.platform == "linux") {
let systemConfigFile = Cc["@mozilla.org/file/local;1"].createInstance(
Ci.nsIFile
@@ -482,6 +491,7 @@ class JSONPoliciesProvider {
return systemConfigFile;
}
}
+#endif
try {
let perUserPath = Services.prefs.getBoolPref(PREF_PER_USER_DIR, false);
@@ -563,6 +573,7 @@ class JSONPoliciesProvider {
}
}
+#ifndef AVOID_SYSTEM_POLICIES
class WindowsGPOPoliciesProvider {
constructor() {
this._policies = null;
@@ -637,6 +648,7 @@ class macOSPoliciesProvider {
return this._failed;
}
}
+#endif
class CombinedProvider {
constructor(primaryProvider, secondaryProvider) {
diff --git a/toolkit/components/enterprisepolicies/moz.build b/toolkit/components/enterprisepolicies/moz.build
index 8f7d7d8cfed7..7528f569bb3e 100644
--- a/toolkit/components/enterprisepolicies/moz.build
+++ b/toolkit/components/enterprisepolicies/moz.build
@@ -19,10 +19,12 @@ TEST_DIRS += [
if CONFIG['MOZ_WIDGET_TOOLKIT'] != "android":
EXTRA_COMPONENTS += [
- 'EnterprisePolicies.js',
'EnterprisePolicies.manifest',
'EnterprisePoliciesContent.js',
]
+ EXTRA_PP_COMPONENTS += [
+ 'EnterprisePolicies.js',
+ ]
if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'windows':
EXTRA_JS_MODULES.policies += [
diff --git a/toolkit/mozapps/update/UpdateService.jsm b/toolkit/mozapps/update/UpdateService.jsm
index 2c565cecadd7..1fb397373151 100644
--- a/toolkit/mozapps/update/UpdateService.jsm
+++ b/toolkit/mozapps/update/UpdateService.jsm
@@ -3268,6 +3268,14 @@ UpdateService.prototype = {
* See nsIUpdateService.idl
*/
get canApplyUpdates() {
+ if (this.disabledByPolicy) {
+ LOG(
+ "UpdateService.canApplyUpdates - unable to apply updates, " +
+ "the option has been disabled by the administrator."
+ );
+ return false;
+ }
+
return getCanApplyUpdates() && hasUpdateMutex();
},
@@ -3275,6 +3283,14 @@ UpdateService.prototype = {
* See nsIUpdateService.idl
*/
get canStageUpdates() {
+ if (this.disabledByPolicy) {
+ LOG(
+ "UpdateService.canStageUpdates - unable to stage updates, " +
+ "the option has been disabled by the administrator."
+ );
+ return false;
+ }
+
return getCanStageUpdates();
},
1
0

[tor-browser/tor-browser-78.11.0esr-10.5-1] Bug 33342: Avoid disconnect search addon error after removal.
by sysrqb@torproject.org 02 Jun '21
by sysrqb@torproject.org 02 Jun '21
02 Jun '21
commit 506e3d0e89e4ee652e7eabb104704607b2ebd83c
Author: Alex Catarineu <acat(a)torproject.org>
Date: Fri Mar 13 18:19:30 2020 +0100
Bug 33342: Avoid disconnect search addon error after removal.
We removed the addon in #32767, but it was still being loaded
from addonStartup.json.lz4 and throwing an error on startup
because its resource: location is not available anymore.
---
toolkit/mozapps/extensions/internal/XPIProvider.jsm | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/toolkit/mozapps/extensions/internal/XPIProvider.jsm b/toolkit/mozapps/extensions/internal/XPIProvider.jsm
index 5e467fb4f14c..794c206fb453 100644
--- a/toolkit/mozapps/extensions/internal/XPIProvider.jsm
+++ b/toolkit/mozapps/extensions/internal/XPIProvider.jsm
@@ -970,6 +970,12 @@ var BuiltInLocation = new (class _BuiltInLocation extends XPIStateLocation {
get enumerable() {
return false;
}
+
+ restore(saved) {
+ super.restore(saved);
+ // Bug 33342: avoid restoring disconnect addon from addonStartup.json.lz4.
+ this.removeAddon("disconnect(a)search.mozilla.org");
+ }
})();
/**
1
0

[tor-browser/tor-browser-78.11.0esr-10.5-1] Bug 28005: Implement .onion alias urlbar rewrites
by sysrqb@torproject.org 02 Jun '21
by sysrqb@torproject.org 02 Jun '21
02 Jun '21
commit d07641143ce06121f3110a405d4ff5fbb4b49535
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.
Bug 34196: Update site info URL with the onion name
---
browser/actors/ClickHandlerChild.jsm | 20 ++
browser/actors/ClickHandlerParent.jsm | 1 +
browser/actors/ContextMenuChild.jsm | 4 +
browser/base/content/browser-places.js | 12 +-
browser/base/content/browser-siteIdentity.js | 12 +-
browser/base/content/browser.js | 43 ++++-
browser/base/content/nsContextMenu.js | 18 ++
browser/base/content/pageinfo/pageInfo.js | 2 +-
browser/base/content/pageinfo/pageInfo.xhtml | 10 +
browser/base/content/pageinfo/security.js | 17 +-
browser/base/content/tabbrowser.js | 7 +
browser/base/content/utilityOverlay.js | 12 ++
browser/components/BrowserGlue.jsm | 8 +
.../onionservices/ExtensionMessaging.jsm | 86 +++++++++
.../onionservices/HttpsEverywhereControl.jsm | 119 ++++++++++++
.../components/onionservices/OnionAliasStore.jsm | 201 +++++++++++++++++++++
browser/components/onionservices/moz.build | 6 +
browser/components/urlbar/UrlbarInput.jsm | 13 +-
docshell/base/nsDocShell.cpp | 52 ++++++
docshell/base/nsDocShell.h | 6 +
docshell/base/nsDocShellLoadState.cpp | 4 +
docshell/base/nsIDocShell.idl | 5 +
docshell/base/nsIWebNavigation.idl | 5 +
docshell/shistory/SessionHistoryEntry.cpp | 14 ++
docshell/shistory/SessionHistoryEntry.h | 1 +
docshell/shistory/nsISHEntry.idl | 5 +
docshell/shistory/nsSHEntry.cpp | 22 ++-
docshell/shistory/nsSHEntry.h | 1 +
dom/interfaces/base/nsIBrowser.idl | 3 +-
dom/ipc/BrowserChild.cpp | 2 +
dom/ipc/BrowserParent.cpp | 3 +-
dom/ipc/PBrowser.ipdl | 1 +
modules/libpref/init/StaticPrefList.yaml | 6 +
netwerk/dns/effective_tld_names.dat | 2 +
netwerk/ipc/DocumentLoadListener.cpp | 10 +
toolkit/content/widgets/browser-custom-element.js | 13 +-
toolkit/modules/sessionstore/SessionHistory.jsm | 5 +
37 files changed, 729 insertions(+), 22 deletions(-)
diff --git a/browser/actors/ClickHandlerChild.jsm b/browser/actors/ClickHandlerChild.jsm
index 7dd060e83061..206a8fc97a4d 100644
--- a/browser/actors/ClickHandlerChild.jsm
+++ b/browser/actors/ClickHandlerChild.jsm
@@ -138,6 +138,26 @@ class ClickHandlerChild extends JSWindowActorChild {
json.originStoragePrincipal = ownerDoc.effectiveStoragePrincipal;
json.triggeringPrincipal = ownerDoc.nodePrincipal;
+ // Check if the link needs to be opened with .tor.onion urlbar rewrites
+ // allowed. Only when the owner doc has onionUrlbarRewritesAllowed = true
+ // and the same origin we should allow this.
+ json.onionUrlbarRewritesAllowed = false;
+ if (this.docShell.onionUrlbarRewritesAllowed) {
+ 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.onionUrlbarRewritesAllowed = 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/ClickHandlerParent.jsm b/browser/actors/ClickHandlerParent.jsm
index 454c0fe69b27..42ab7a0f6e2a 100644
--- a/browser/actors/ClickHandlerParent.jsm
+++ b/browser/actors/ClickHandlerParent.jsm
@@ -102,6 +102,7 @@ class ClickHandlerParent extends JSWindowActorParent {
charset: browser.characterSet,
referrerInfo: E10SUtils.deserializeReferrerInfo(data.referrerInfo),
allowMixedContent: data.allowMixedContent,
+ onionUrlbarRewritesAllowed: data.onionUrlbarRewritesAllowed,
isContentWindowPrivate: data.isContentWindowPrivate,
originPrincipal: data.originPrincipal,
originStoragePrincipal: data.originStoragePrincipal,
diff --git a/browser/actors/ContextMenuChild.jsm b/browser/actors/ContextMenuChild.jsm
index 16a3f8ecbc81..1a1b38aa6375 100644
--- a/browser/actors/ContextMenuChild.jsm
+++ b/browser/actors/ContextMenuChild.jsm
@@ -575,6 +575,9 @@ class ContextMenuChild extends JSWindowActorChild {
// The same-origin check will be done in nsContextMenu.openLinkInTab.
let parentAllowsMixedContent = !!this.docShell.mixedContentChannel;
+ let parentAllowsOnionUrlbarRewrites = this.docShell
+ .onionUrlbarRewritesAllowed;
+
let disableSetDesktopBackground = null;
// Media related cache info parent needs for saving
@@ -687,6 +690,7 @@ class ContextMenuChild extends JSWindowActorChild {
frameBrowsingContextID,
disableSetDesktopBackground,
parentAllowsMixedContent,
+ parentAllowsOnionUrlbarRewrites,
};
if (context.inFrame && !context.inSrcdocFrame) {
diff --git a/browser/base/content/browser-places.js b/browser/base/content/browser-places.js
index d4b71f87da04..9a9bb3e0dad4 100644
--- a/browser/base/content/browser-places.js
+++ b/browser/base/content/browser-places.js
@@ -452,7 +452,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;
@@ -556,7 +557,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)) {
@@ -1655,14 +1656,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-siteIdentity.js b/browser/base/content/browser-siteIdentity.js
index b7fa432d9478..539d6d4056a3 100644
--- a/browser/base/content/browser-siteIdentity.js
+++ b/browser/base/content/browser-siteIdentity.js
@@ -474,13 +474,13 @@ var gIdentityHandler = {
* nsIURI for which the identity UI should be displayed, already
* processed by createExposableURI.
*/
- updateIdentity(state, uri) {
+ updateIdentity(state, uri, onionAliasURI) {
let shouldHidePopup = this._uri && this._uri.spec != uri.spec;
this._state = state;
// Firstly, populate the state properties required to display the UI. See
// the documentation of the individual properties for details.
- this.setURI(uri);
+ this.setURI(uri, onionAliasURI);
this._secInfo = gBrowser.securityUI.secInfo;
this._isSecureContext = gBrowser.securityUI.isSecureContext;
@@ -566,17 +566,18 @@ var gIdentityHandler = {
* Attempt to provide proper IDN treatment for host names
*/
getEffectiveHost() {
+ let uri = this._onionAliasURI || this._uri;
if (!this._IDNService) {
this._IDNService = Cc["@mozilla.org/network/idn-service;1"].getService(
Ci.nsIIDNService
);
}
try {
- return this._IDNService.convertToDisplayIDN(this._uri.host, {});
+ return this._IDNService.convertToDisplayIDN(uri.host, {});
} catch (e) {
// If something goes wrong (e.g. host is an IP address) just fail back
// to the full domain.
- return this._uri.host;
+ return uri.host;
}
},
@@ -1000,8 +1001,9 @@ var gIdentityHandler = {
this.updateSitePermissions();
},
- setURI(uri) {
+ setURI(uri, onionAliasURI) {
this._uri = uri;
+ this._onionAliasURI = onionAliasURI;
try {
// Account for file: urls and catch when "" is the value
diff --git a/browser/base/content/browser.js b/browser/base/content/browser.js
index 9f5f0c608536..bd5f10cb6f64 100644
--- a/browser/base/content/browser.js
+++ b/browser/base/content/browser.js
@@ -77,6 +77,7 @@ XPCOMUtils.defineLazyModuleGetters(this, {
TabCrashHandler: "resource:///modules/ContentCrashHandlers.jsm",
TelemetryEnvironment: "resource://gre/modules/TelemetryEnvironment.jsm",
Translation: "resource:///modules/translation/TranslationParent.jsm",
+ OnionAliasStore: "resource:///modules/OnionAliasStore.jsm",
UITour: "resource:///modules/UITour.jsm",
UpdateUtils: "resource://gre/modules/UpdateUtils.jsm",
UrlbarInput: "resource:///modules/UrlbarInput.jsm",
@@ -2325,6 +2326,7 @@ var gBrowserInit = {
// [9]: allowInheritPrincipal (bool)
// [10]: csp (nsIContentSecurityPolicy)
// [11]: nsOpenWindowInfo
+ // [12]: onionUrlbarRewritesAllowed (bool)
let userContextId =
window.arguments[5] != undefined
? window.arguments[5]
@@ -2344,7 +2346,8 @@ var gBrowserInit = {
// TODO fix allowInheritPrincipal to default to false.
// Default to true unless explicitly set to false because of bug 1475201.
window.arguments[9] !== false,
- window.arguments[10]
+ window.arguments[10],
+ window.arguments[12]
);
window.focus();
} else {
@@ -3230,7 +3233,8 @@ function loadURI(
forceAboutBlankViewerInCurrent,
triggeringPrincipal,
allowInheritPrincipal = false,
- csp = null
+ csp = null,
+ onionUrlbarRewritesAllowed = false
) {
if (!triggeringPrincipal) {
throw new Error("Must load with a triggering Principal");
@@ -3248,6 +3252,7 @@ function loadURI(
csp,
forceAboutBlankViewerInCurrent,
allowInheritPrincipal,
+ onionUrlbarRewritesAllowed,
});
} catch (e) {
Cu.reportError(e);
@@ -5359,11 +5364,24 @@ var XULBrowserWindow = {
this.reloadCommand.removeAttribute("disabled");
}
+ // The onion memorable alias needs to be used in gURLBar.setURI, but also in
+ // other parts of the code (like the bookmarks UI), so we save it.
+ if (gBrowser.selectedBrowser.onionUrlbarRewritesAllowed) {
+ 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
- gURLBar.setURI(aLocationURI, aIsSimulated);
+ gURLBar.setURI(
+ gBrowser.selectedBrowser.currentOnionAliasURI || aLocationURI,
+ aIsSimulated
+ );
BookmarkingUI.onLocationChange();
@@ -5534,6 +5552,7 @@ var XULBrowserWindow = {
// Don't need to do anything if the data we use to update the UI hasn't
// changed
let uri = gBrowser.currentURI;
+ let onionAliasURI = gBrowser.selectedBrowser.currentOnionAliasURI;
let spec = uri.spec;
if (this._state == aState && this._lastLocation == spec) {
// Switching to a tab of the same URL doesn't change most security
@@ -5551,7 +5570,7 @@ var XULBrowserWindow = {
try {
uri = Services.io.createExposableURI(uri);
} catch (e) {}
- gIdentityHandler.updateIdentity(this._state, uri);
+ gIdentityHandler.updateIdentity(this._state, uri, onionAliasURI);
},
// simulate all change notifications after switching tabs
@@ -7011,6 +7030,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 onionUrlbarRewritesAllowed = true
+ // and the same origin we should allow this.
+ let persistOnionUrlbarRewritesAllowedInChildTab = false;
+ if (where == "tab" && gBrowser.docShell.onionUrlbarRewritesAllowed) {
+ const sm = Services.scriptSecurityManager;
+ try {
+ let tURI = makeURI(href);
+ let isPrivateWin =
+ doc.nodePrincipal.originAttributes.privateBrowsingId > 0;
+ sm.checkSameOriginURI(doc.documentURIObject, tURI, false, isPrivateWin);
+ persistOnionUrlbarRewritesAllowedInChildTab = true;
+ } catch (e) {}
+ }
+
let frameOuterWindowID = WebNavigationFrames.getFrameId(doc.defaultView);
urlSecurityCheck(href, doc.nodePrincipal);
@@ -7023,6 +7057,7 @@ function handleLinkClick(event, href, linkNode) {
triggeringPrincipal: doc.nodePrincipal,
csp: doc.csp,
frameOuterWindowID,
+ onionUrlbarRewritesAllowed: persistOnionUrlbarRewritesAllowedInChildTab,
};
// The new tab/window must use the same userContextId
diff --git a/browser/base/content/nsContextMenu.js b/browser/base/content/nsContextMenu.js
index 354b504ce0b4..ca351c71f1cb 100644
--- a/browser/base/content/nsContextMenu.js
+++ b/browser/base/content/nsContextMenu.js
@@ -57,6 +57,7 @@ function openContextMenu(aMessage, aBrowser, aActor) {
disableSetDesktopBackground: data.disableSetDesktopBackground,
loginFillInfo: data.loginFillInfo,
parentAllowsMixedContent: data.parentAllowsMixedContent,
+ parentAllowsOnionUrlbarRewrites: data.parentAllowsOnionUrlbarRewrites,
userContextId: data.userContextId,
webExtContextData: data.webExtContextData,
};
@@ -1059,6 +1060,7 @@ class nsContextMenu {
triggeringPrincipal: this.principal,
csp: this.csp,
frameOuterWindowID: this.contentData.frameOuterWindowID,
+ onionUrlbarRewritesAllowed: false,
};
for (let p in extra) {
params[p] = extra[p];
@@ -1082,6 +1084,22 @@ class nsContextMenu {
}
params.referrerInfo = referrerInfo;
+
+ // Check if the link needs to be opened with .tor.onion urlbar rewrites
+ // allowed. Only when parent has onionUrlbarRewritesAllowed = true
+ // and the same origin we should allow this.
+ if (this.contentData.parentAllowsOnionUrlbarRewrites) {
+ let referrerURI = this.contentData.documentURIObject;
+ const sm = Services.scriptSecurityManager;
+ try {
+ let targetURI = this.linkURI;
+ let isPrivateWin =
+ this.browser.contentPrincipal.originAttributes.privateBrowsingId > 0;
+ sm.checkSameOriginURI(referrerURI, targetURI, false, isPrivateWin);
+ params.onionUrlbarRewritesAllowed = true;
+ } catch (e) {}
+ }
+
return params;
}
diff --git a/browser/base/content/pageinfo/pageInfo.js b/browser/base/content/pageinfo/pageInfo.js
index 664dace84d9f..cd03cea3b6d9 100644
--- a/browser/base/content/pageinfo/pageInfo.js
+++ b/browser/base/content/pageinfo/pageInfo.js
@@ -390,7 +390,7 @@ async function onNonMediaPageInfoLoad(browser, pageInfoData, imageInfo) {
);
}
onLoadPermission(uri, principal);
- securityOnLoad(uri, windowInfo);
+ securityOnLoad(uri, windowInfo, browser.currentOnionAliasURI);
}
function resetPageInfo(args) {
diff --git a/browser/base/content/pageinfo/pageInfo.xhtml b/browser/base/content/pageinfo/pageInfo.xhtml
index f40ffd3778d8..a23f2bb5748c 100644
--- a/browser/base/content/pageinfo/pageInfo.xhtml
+++ b/browser/base/content/pageinfo/pageInfo.xhtml
@@ -312,6 +312,16 @@
<input id="security-identity-domain-value" readonly="readonly"/>
</td>
</tr>
+ <!-- Onion Alias -->
+ <tr id="security-view-identity-onionalias-row">
+ <th>
+ <xul:label id="security-view-identity-onionalias"
+ control="security-view-identity-onionalias-value"/>
+ </th>
+ <td>
+ <input id="security-view-identity-onionalias-value" readonly="true"/>
+ </td>
+ </tr>
<!-- Owner -->
<tr>
<th>
diff --git a/browser/base/content/pageinfo/security.js b/browser/base/content/pageinfo/security.js
index 4331ebc4b219..29395e96ce57 100644
--- a/browser/base/content/pageinfo/security.js
+++ b/browser/base/content/pageinfo/security.js
@@ -250,7 +250,7 @@ var security = {
},
};
-async function securityOnLoad(uri, windowInfo) {
+async function securityOnLoad(uri, windowInfo, onionAliasURI) {
await security.init(uri, windowInfo);
let info = security.securityInfo;
@@ -263,6 +263,21 @@ async function securityOnLoad(uri, windowInfo) {
}
document.getElementById("securityTab").hidden = false;
+ if (onionAliasURI) {
+ setText(
+ "security-view-identity-onionalias",
+ gTorButtonBundle.GetStringFromName("pageInfo_OnionName")
+ );
+ setText("security-view-identity-onionalias-value", onionAliasURI.host);
+ document.getElementById(
+ "security-view-identity-onionalias-row"
+ ).hidden = false;
+ } else {
+ document.getElementById(
+ "security-view-identity-onionalias-row"
+ ).hidden = true;
+ }
+
/* Set Identity section text */
setText("security-identity-domain-value", windowInfo.hostName);
diff --git a/browser/base/content/tabbrowser.js b/browser/base/content/tabbrowser.js
index 8ce4a2710cb8..8c313eaaffcb 100644
--- a/browser/base/content/tabbrowser.js
+++ b/browser/base/content/tabbrowser.js
@@ -1547,6 +1547,7 @@
var aRelatedToCurrent;
var aAllowInheritPrincipal;
var aAllowMixedContent;
+ var aOnionUrlbarRewritesAllowed;
var aSkipAnimation;
var aForceNotRemote;
var aPreferredRemoteType;
@@ -1577,6 +1578,7 @@
aRelatedToCurrent = params.relatedToCurrent;
aAllowInheritPrincipal = !!params.allowInheritPrincipal;
aAllowMixedContent = params.allowMixedContent;
+ aOnionUrlbarRewritesAllowed = params.onionUrlbarRewritesAllowed;
aSkipAnimation = params.skipAnimation;
aForceNotRemote = params.forceNotRemote;
aPreferredRemoteType = params.preferredRemoteType;
@@ -1618,6 +1620,7 @@
relatedToCurrent: aRelatedToCurrent,
skipAnimation: aSkipAnimation,
allowMixedContent: aAllowMixedContent,
+ onionUrlbarRewritesAllowed: aOnionUrlbarRewritesAllowed,
forceNotRemote: aForceNotRemote,
createLazyBrowser: aCreateLazyBrowser,
preferredRemoteType: aPreferredRemoteType,
@@ -2504,6 +2507,7 @@
{
allowInheritPrincipal,
allowMixedContent,
+ onionUrlbarRewritesAllowed,
allowThirdPartyFixup,
bulkOrderedOpen,
charset,
@@ -2833,6 +2837,9 @@
if (allowMixedContent) {
flags |= Ci.nsIWebNavigation.LOAD_FLAGS_ALLOW_MIXED_CONTENT;
}
+ if (onionUrlbarRewritesAllowed) {
+ 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 a23d6f05e6a7..eb13d5a3435c 100644
--- a/browser/base/content/utilityOverlay.js
+++ b/browser/base/content/utilityOverlay.js
@@ -367,6 +367,7 @@ function openLinkIn(url, where, params) {
var aRelatedToCurrent = params.relatedToCurrent;
var aAllowInheritPrincipal = !!params.allowInheritPrincipal;
var aAllowMixedContent = params.allowMixedContent;
+ var aOnionUrlbarRewritesAllowed = params.onionUrlbarRewritesAllowed;
var aForceAllowDataURI = params.forceAllowDataURI;
var aInBackground = params.inBackground;
var aInitiatingDoc = params.initiatingDoc;
@@ -482,6 +483,11 @@ function openLinkIn(url, where, params) {
].createInstance(Ci.nsISupportsPRBool);
allowThirdPartyFixupSupports.data = aAllowThirdPartyFixup;
+ var onionUrlbarRewritesAllowed = Cc[
+ "@mozilla.org/supports-PRBool;1"
+ ].createInstance(Ci.nsISupportsPRBool);
+ onionUrlbarRewritesAllowed.data = aOnionUrlbarRewritesAllowed;
+
var userContextIdSupports = Cc[
"@mozilla.org/supports-PRUint32;1"
].createInstance(Ci.nsISupportsPRUint32);
@@ -498,6 +504,8 @@ function openLinkIn(url, where, params) {
sa.appendElement(aTriggeringPrincipal);
sa.appendElement(null); // allowInheritPrincipal
sa.appendElement(aCsp);
+ sa.appendElement(null); // nsOpenWindowInfo
+ sa.appendElement(onionUrlbarRewritesAllowed);
const sourceWindow = w || window;
let win;
@@ -614,6 +622,9 @@ function openLinkIn(url, where, params) {
if (aForceAllowDataURI) {
flags |= Ci.nsIWebNavigation.LOAD_FLAGS_FORCE_ALLOW_DATA_URI;
}
+ if (aOnionUrlbarRewritesAllowed) {
+ flags |= Ci.nsIWebNavigation.LOAD_FLAGS_ALLOW_ONION_URLBAR_REWRITES;
+ }
let { URI_INHERITS_SECURITY_CONTEXT } = Ci.nsIProtocolHandler;
if (
@@ -661,6 +672,7 @@ function openLinkIn(url, where, params) {
relatedToCurrent: aRelatedToCurrent,
skipAnimation: aSkipTabAnimation,
allowMixedContent: aAllowMixedContent,
+ onionUrlbarRewritesAllowed: aOnionUrlbarRewritesAllowed,
userContextId: aUserContextId,
originPrincipal: aPrincipal,
originStoragePrincipal: aStoragePrincipal,
diff --git a/browser/components/BrowserGlue.jsm b/browser/components/BrowserGlue.jsm
index 7d147d01d561..d30abff54562 100644
--- a/browser/components/BrowserGlue.jsm
+++ b/browser/components/BrowserGlue.jsm
@@ -703,6 +703,7 @@ XPCOMUtils.defineLazyModuleGetters(this, {
TabCrashHandler: "resource:///modules/ContentCrashHandlers.jsm",
TabUnloader: "resource:///modules/TabUnloader.jsm",
TRRRacer: "resource:///modules/TRRPerformance.jsm",
+ OnionAliasStore: "resource:///modules/OnionAliasStore.jsm",
UIState: "resource://services-sync/UIState.jsm",
WebChannel: "resource://gre/modules/WebChannel.jsm",
WindowsRegistry: "resource://gre/modules/WindowsRegistry.jsm",
@@ -2046,6 +2047,7 @@ BrowserGlue.prototype = {
Normandy.uninit();
RFPHelper.uninit();
+ OnionAliasStore.uninit();
},
// Set up a listener to enable/disable the screenshots extension
@@ -2412,6 +2414,12 @@ BrowserGlue.prototype = {
},
},
+ {
+ task: () => {
+ OnionAliasStore.init();
+ },
+ },
+
{
task: () => {
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..60c3b5fca282
--- /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:
+ "p10BbUVc5Xj2S_-MH3bACNBaISo_r9e3PVPyTTjsGsdg2qSXvqUO42fBtpFAy0zUzIGS83v4JjiRdvKJaZTIvbC8AcpymzdsTqujMm8RPTSy3hO_8mXzGa4DEsIB1uNLnUWRBKXvSGCmT9kFyxhTpkYqokNBzafVihTU34tN2Md1xFHnmZGqfYtPtbJLWAa5Z1M11EyR4lIyUxIiPTV9t1XstDbWr3iS83REJrGEFmjG1-BAgx8_lDUTa41799N2yYEhgZud7bL0M3ei8s5OERjiion5uANkUV3-s2QqUZjiVA-XR_HizXjciaUWNd683KqekpNOZ_0STh_UGwpcwU-KwG07QyiCrLrRpz8S_vH8CqGrrcWY3GSzYe9dp34jJdO65oA-G8tK6fMXtvTCFDZI6oNNaXJH71F5J0YbqO2ZqwKYc2WSi0gKVl2wd9roOVjaBmkJqvocntYuNM7t38fDEWHn5KUkmrTbiG68Cy56tDUfpKl3D9Uj4LaMvxJ1tKGvzQ4k_60odT7gIxu6DqYjXUHZpwPsSGBq3njaD7boe4CUXF2K7ViOc87BsKxRNCzDD8OklRjjXzOTOBH3PqFJ93CJ-4ECE5t9STU20aZ8E-2zKB8vjKyCySE4-kcIvBBsnkwVaJTPy9Ft1qYybo-soXEWVEZATANNWklBt8k",
+ },
+ update_path_prefix: "https://securedrop.org/https-everywhere/",
+ 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..66cf569227bf
--- /dev/null
+++ b/browser/components/onionservices/OnionAliasStore.jsm
@@ -0,0 +1,201 @@
+// 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;
+ this._updateChannelInstalled = false;
+ }
+
+ 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();
+
+ // 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.installTorOnionUpdateChannel();
+ this._updateChannelInstalled = true;
+ 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: ${e.message}`);
+ }
+
+ // Setup checker for https-everywhere ruleset updates
+ if (this._updateChannelInstalled) {
+ 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 db1c497bcace..13b1279105f2 100644
--- a/browser/components/urlbar/UrlbarInput.jsm
+++ b/browser/components/urlbar/UrlbarInput.jsm
@@ -277,7 +277,10 @@ class UrlbarInput {
// bar if the user has deleted the URL and we'd just put the same URL
// back. See bug 304198.
if (value === null) {
- uri = uri || this.window.gBrowser.currentURI;
+ uri =
+ uri ||
+ this.window.gBrowser.selectedBrowser.currentOnionAliasURI ||
+ this.window.gBrowser.currentURI;
// Strip off usernames and passwords for the location bar
try {
uri = Services.io.createExposableURI(uri);
@@ -1541,7 +1544,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.currentOnionAliasURI
+ ) {
uri = this.window.gBrowser.currentURI;
} else {
// The value could be:
diff --git a/docshell/base/nsDocShell.cpp b/docshell/base/nsDocShell.cpp
index 8731e44dd4eb..bf9639c82612 100644
--- a/docshell/base/nsDocShell.cpp
+++ b/docshell/base/nsDocShell.cpp
@@ -5657,6 +5657,10 @@ void nsDocShell::OnRedirectStateChange(nsIChannel* aOldChannel,
return;
}
+ if (!mOnionUrlbarRewritesAllowed && IsTorOnionRedirect(oldURI, newURI)) {
+ mOnionUrlbarRewritesAllowed = true;
+ }
+
// DocumentChannel adds redirect chain to global history in the parent
// process. The redirect chain can't be queried from the content process, so
// there's no need to update global history here.
@@ -8693,6 +8697,20 @@ nsresult nsDocShell::HandleSameDocumentNavigation(
return NS_OK;
}
+/* static */
+bool nsDocShell::IsTorOnionRedirect(nsIURI* aOldURI, nsIURI* aNewURI) {
+ nsAutoCString oldHost;
+ nsAutoCString newHost;
+ if (aOldURI && aNewURI && NS_SUCCEEDED(aOldURI->GetHost(oldHost)) &&
+ StringEndsWith(oldHost, NS_LITERAL_CSTRING(".tor.onion")) &&
+ NS_SUCCEEDED(aNewURI->GetHost(newHost)) &&
+ StringEndsWith(newHost, NS_LITERAL_CSTRING(".onion")) &&
+ !StringEndsWith(newHost, NS_LITERAL_CSTRING(".tor.onion"))) {
+ return true;
+ }
+ return false;
+ }
+
nsresult nsDocShell::InternalLoad(nsDocShellLoadState* aLoadState,
nsIDocShell** aDocShell,
nsIRequest** aRequest) {
@@ -8844,6 +8862,30 @@ nsresult nsDocShell::InternalLoad(nsDocShellLoadState* aLoadState,
mAllowKeywordFixup =
aLoadState->HasLoadFlags(INTERNAL_LOAD_FLAGS_ALLOW_THIRD_PARTY_FIXUP);
+
+ if (mOnionUrlbarRewritesAllowed) {
+ mOnionUrlbarRewritesAllowed = false;
+ nsCOMPtr<nsIURI> referrer;
+ nsIReferrerInfo* referrerInfo = aLoadState->GetReferrerInfo();
+ if (referrerInfo) {
+ referrerInfo->GetOriginalReferrer(getter_AddRefs(referrer));
+ bool isPrivateWin = false;
+ Document* doc = GetDocument();
+ if (doc) {
+ isPrivateWin =
+ doc->NodePrincipal()->OriginAttributesRef().mPrivateBrowsingId > 0;
+ nsCOMPtr<nsIScriptSecurityManager> secMan =
+ do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID);
+ mOnionUrlbarRewritesAllowed =
+ secMan && NS_SUCCEEDED(secMan->CheckSameOriginURI(
+ aLoadState->URI(), referrer, false, isPrivateWin));
+ }
+ }
+ }
+ mOnionUrlbarRewritesAllowed =
+ mOnionUrlbarRewritesAllowed ||
+ aLoadState->HasLoadFlags(INTERNAL_LOAD_FLAGS_ALLOW_ONION_URLBAR_REWRITES);
+
mURIResultedInDocument = false; // reset the clock...
// See if this is actually a load between two history entries for the same
@@ -10996,6 +11038,7 @@ nsresult nsDocShell::AddToSessionHistory(
mDynamicallyCreated, originalURI, resultPrincipalURI,
loadReplace, referrerInfo, srcdoc, srcdocEntry, baseURI,
saveLayoutState, expired);
+ entry->SetOnionUrlbarRewritesAllowed(mOnionUrlbarRewritesAllowed);
if (root == static_cast<nsIDocShellTreeItem*>(this) && GetSessionHistory()) {
bool shouldPersist = ShouldAddToSessionHistory(aURI, aChannel);
@@ -12793,3 +12836,12 @@ bool nsDocShell::GetIsAttemptingToNavigate() {
return false;
}
+
+NS_IMETHODIMP
+nsDocShell::GetOnionUrlbarRewritesAllowed(bool* aOnionUrlbarRewritesAllowed) {
+ NS_ENSURE_ARG(aOnionUrlbarRewritesAllowed);
+ *aOnionUrlbarRewritesAllowed =
+ StaticPrefs::browser_urlbar_onionRewrites_enabled() &&
+ mOnionUrlbarRewritesAllowed;
+ return NS_OK;
+}
diff --git a/docshell/base/nsDocShell.h b/docshell/base/nsDocShell.h
index dcffed8e5537..d403a06f4c9f 100644
--- a/docshell/base/nsDocShell.h
+++ b/docshell/base/nsDocShell.h
@@ -152,6 +152,9 @@ class nsDocShell final : public nsDocLoader,
// Whether the load should go through LoadURIDelegate.
INTERNAL_LOAD_FLAGS_BYPASS_LOAD_URI_DELEGATE = 0x2000,
+
+ // Whether rewriting the urlbar to a short .onion alias is allowed.
+ INTERNAL_LOAD_FLAGS_ALLOW_ONION_URLBAR_REWRITES = 0x4000,
};
// Event type dispatched by RestorePresentation
@@ -582,6 +585,8 @@ class nsDocShell final : public nsDocLoader,
virtual void DestroyChildren() override;
+ static bool IsTorOnionRedirect(nsIURI* aOldURI, nsIURI* aNewURI);
+
// Overridden from nsDocLoader, this provides more information than the
// normal OnStateChange with flags STATE_REDIRECTING
virtual void OnRedirectStateChange(nsIChannel* aOldChannel,
@@ -1264,6 +1269,7 @@ class nsDocShell final : public nsDocLoader,
bool mCSSErrorReportingEnabled : 1;
bool mAllowAuth : 1;
bool mAllowKeywordFixup : 1;
+ bool mOnionUrlbarRewritesAllowed : 1;
bool mIsOffScreenBrowser : 1;
bool mDisableMetaRefreshWhenInactive : 1;
bool mIsAppTab : 1;
diff --git a/docshell/base/nsDocShellLoadState.cpp b/docshell/base/nsDocShellLoadState.cpp
index d91bb6034f9d..fe1216bd2509 100644
--- a/docshell/base/nsDocShellLoadState.cpp
+++ b/docshell/base/nsDocShellLoadState.cpp
@@ -730,6 +730,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 01dc4734eb19..305acfd3a98f 100644
--- a/docshell/base/nsIDocShell.idl
+++ b/docshell/base/nsIDocShell.idl
@@ -1019,4 +1019,9 @@ interface nsIDocShell : nsIDocShellTreeItem
* until session history state is moved into the parent process.
*/
void persistLayoutHistoryState();
+
+ /**
+ * Whether rewriting the urlbar to a short .onion alias is allowed.
+ */
+ [infallible] readonly attribute boolean onionUrlbarRewritesAllowed;
};
diff --git a/docshell/base/nsIWebNavigation.idl b/docshell/base/nsIWebNavigation.idl
index bbc3eb7583a2..a4cceb52b2a0 100644
--- a/docshell/base/nsIWebNavigation.idl
+++ b/docshell/base/nsIWebNavigation.idl
@@ -237,6 +237,11 @@ interface nsIWebNavigation : nsISupports
*/
const unsigned long LOAD_FLAGS_BYPASS_LOAD_URI_DELEGATE = 0x4000000;
+ /**
+ * Allow rewriting the urlbar to a short .onion alias.
+ */
+ const unsigned long LOAD_FLAGS_ALLOW_ONION_URLBAR_REWRITES = 0x8000000;
+
/**
* 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
diff --git a/docshell/shistory/SessionHistoryEntry.cpp b/docshell/shistory/SessionHistoryEntry.cpp
index 07a28d1291c9..566b7d68fae5 100644
--- a/docshell/shistory/SessionHistoryEntry.cpp
+++ b/docshell/shistory/SessionHistoryEntry.cpp
@@ -490,6 +490,20 @@ SessionHistoryEntry::SetPersist(bool aPersist) {
return NS_OK;
}
+NS_IMETHODIMP
+SessionHistoryEntry::GetOnionUrlbarRewritesAllowed(
+ bool* aOnionUrlbarRewritesAllowed) {
+ *aOnionUrlbarRewritesAllowed = mInfo->mOnionUrlbarRewritesAllowed;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+SessionHistoryEntry::SetOnionUrlbarRewritesAllowed(
+ bool aOnionUrlbarRewritesAllowed) {
+ mInfo->mOnionUrlbarRewritesAllowed = aOnionUrlbarRewritesAllowed;
+ return NS_OK;
+}
+
NS_IMETHODIMP
SessionHistoryEntry::GetScrollPosition(int32_t* aX, int32_t* aY) {
*aX = mInfo->mScrollPositionX;
diff --git a/docshell/shistory/SessionHistoryEntry.h b/docshell/shistory/SessionHistoryEntry.h
index fa6108952688..c51682a65b0a 100644
--- a/docshell/shistory/SessionHistoryEntry.h
+++ b/docshell/shistory/SessionHistoryEntry.h
@@ -58,6 +58,7 @@ class SessionHistoryInfo {
bool mIsSrcdocEntry = false;
bool mScrollRestorationIsManual = false;
bool mPersist = false;
+ bool mOnionUrlbarRewritesAllowed = false;
};
// XXX Not sure that the id shouldn't just live in SessionHistoryInfo.
diff --git a/docshell/shistory/nsISHEntry.idl b/docshell/shistory/nsISHEntry.idl
index 8bbf2a68687c..bf410bfcc05a 100644
--- a/docshell/shistory/nsISHEntry.idl
+++ b/docshell/shistory/nsISHEntry.idl
@@ -242,6 +242,11 @@ interface nsISHEntry : nsISupports
*/
[infallible] attribute boolean persist;
+ /**
+ * Whether rewriting the urlbar to a short .onion alias is allowed.
+ */
+ [infallible] attribute boolean onionUrlbarRewritesAllowed;
+
/**
* 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 229b15eff25d..12d38f4c55fe 100644
--- a/docshell/shistory/nsSHEntry.cpp
+++ b/docshell/shistory/nsSHEntry.cpp
@@ -44,7 +44,8 @@ nsSHEntry::nsSHEntry(nsISHistory* aSHistory)
mIsSrcdocEntry(false),
mScrollRestorationIsManual(false),
mLoadedInThisProcess(false),
- mPersist(true) {}
+ mPersist(true),
+ mOnionUrlbarRewritesAllowed(false) {}
nsSHEntry::nsSHEntry(const nsSHEntry& aOther)
: mShared(aOther.mShared),
@@ -70,7 +71,8 @@ nsSHEntry::nsSHEntry(const nsSHEntry& aOther)
mIsSrcdocEntry(aOther.mIsSrcdocEntry),
mScrollRestorationIsManual(false),
mLoadedInThisProcess(aOther.mLoadedInThisProcess),
- mPersist(aOther.mPersist) {}
+ mPersist(aOther.mPersist),
+ mOnionUrlbarRewritesAllowed(aOther.mOnionUrlbarRewritesAllowed) {}
nsSHEntry::~nsSHEntry() {
// Null out the mParent pointers on all our kids.
@@ -824,6 +826,18 @@ nsSHEntry::SetPersist(bool aPersist) {
return NS_OK;
}
+NS_IMETHODIMP
+nsSHEntry::GetOnionUrlbarRewritesAllowed(bool* aOnionUrlbarRewritesAllowed) {
+ *aOnionUrlbarRewritesAllowed = mOnionUrlbarRewritesAllowed;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsSHEntry::SetOnionUrlbarRewritesAllowed(bool aOnionUrlbarRewritesAllowed) {
+ mOnionUrlbarRewritesAllowed = aOnionUrlbarRewritesAllowed;
+ return NS_OK;
+}
+
NS_IMETHODIMP
nsSHEntry::CreateLoadInfo(nsDocShellLoadState** aLoadState) {
nsCOMPtr<nsIURI> uri = GetURI();
@@ -873,6 +887,10 @@ nsSHEntry::CreateLoadInfo(nsDocShellLoadState** aLoadState) {
} else {
srcdoc = VoidString();
}
+ if (GetOnionUrlbarRewritesAllowed()) {
+ flags |= nsDocShell::InternalLoad::
+ INTERNAL_LOAD_FLAGS_ALLOW_ONION_URLBAR_REWRITES;
+ }
loadState->SetSrcdocData(srcdoc);
loadState->SetBaseURI(baseURI);
loadState->SetLoadFlags(flags);
diff --git a/docshell/shistory/nsSHEntry.h b/docshell/shistory/nsSHEntry.h
index 351f6f200a33..6bc9de521437 100644
--- a/docshell/shistory/nsSHEntry.h
+++ b/docshell/shistory/nsSHEntry.h
@@ -63,6 +63,7 @@ class nsSHEntry : public nsISHEntry {
bool mScrollRestorationIsManual;
bool mLoadedInThisProcess;
bool mPersist;
+ bool mOnionUrlbarRewritesAllowed;
};
#endif /* nsSHEntry_h */
diff --git a/dom/interfaces/base/nsIBrowser.idl b/dom/interfaces/base/nsIBrowser.idl
index 300b09e13824..a9ff00e964b7 100644
--- a/dom/interfaces/base/nsIBrowser.idl
+++ b/dom/interfaces/base/nsIBrowser.idl
@@ -158,7 +158,8 @@ interface nsIBrowser : nsISupports
in uint64_t aInnerWindowID,
in boolean aHasRequestContextID,
in uint64_t aRequestContextID,
- in AString aContentType);
+ in AString aContentType,
+ in boolean aOnionUrlbarRewritesAllowed);
/**
* Called by Gecko when it wants to change the process which is currently
diff --git a/dom/ipc/BrowserChild.cpp b/dom/ipc/BrowserChild.cpp
index 2b17323d8a93..f72aa8faa11d 100644
--- a/dom/ipc/BrowserChild.cpp
+++ b/dom/ipc/BrowserChild.cpp
@@ -3645,6 +3645,8 @@ NS_IMETHODIMP BrowserChild::OnLocationChange(nsIWebProgress* aWebProgress,
docShell->GetMayEnableCharacterEncodingMenu();
locationChangeData->charsetAutodetected() =
docShell->GetCharsetAutodetected();
+ locationChangeData->onionUrlbarRewritesAllowed() =
+ docShell->GetOnionUrlbarRewritesAllowed();
locationChangeData->contentPrincipal() = document->NodePrincipal();
locationChangeData->contentStoragePrincipal() =
diff --git a/dom/ipc/BrowserParent.cpp b/dom/ipc/BrowserParent.cpp
index 7749792cafb4..086ecd95e9e7 100644
--- a/dom/ipc/BrowserParent.cpp
+++ b/dom/ipc/BrowserParent.cpp
@@ -2698,7 +2698,8 @@ mozilla::ipc::IPCResult BrowserParent::RecvOnLocationChange(
aWebProgressData->innerDOMWindowID(),
aLocationChangeData->requestContextID().isSome(),
aLocationChangeData->requestContextID().valueOr(0),
- aLocationChangeData->contentType());
+ aLocationChangeData->contentType(),
+ aLocationChangeData->onionUrlbarRewritesAllowed());
}
Unused << managerAsListener->OnLocationChange(webProgress, request, aLocation,
diff --git a/dom/ipc/PBrowser.ipdl b/dom/ipc/PBrowser.ipdl
index f36e2c6db353..15756e7fef4f 100644
--- a/dom/ipc/PBrowser.ipdl
+++ b/dom/ipc/PBrowser.ipdl
@@ -142,6 +142,7 @@ struct WebProgressLocationChangeData
bool isSyntheticDocument;
bool mayEnableCharacterEncodingMenu;
bool charsetAutodetected;
+ bool onionUrlbarRewritesAllowed;
nsString contentType;
nsString title;
nsString charset;
diff --git a/modules/libpref/init/StaticPrefList.yaml b/modules/libpref/init/StaticPrefList.yaml
index e506e8257718..f1f2ccdf0cce 100644
--- a/modules/libpref/init/StaticPrefList.yaml
+++ b/modules/libpref/init/StaticPrefList.yaml
@@ -1077,6 +1077,12 @@
value: true
mirror: always
+ # Whether rewriting the urlbar to a short .onion alias is allowed.
+- name: browser.urlbar.onionRewrites.enabled
+ type: RelaxedAtomicBool
+ value: true
+ mirror: always
+
- name: browser.viewport.desktopWidth
type: RelaxedAtomicInt32
value: 980
diff --git a/netwerk/dns/effective_tld_names.dat b/netwerk/dns/effective_tld_names.dat
index 19760224ee4c..d6d655de4fb6 100644
--- a/netwerk/dns/effective_tld_names.dat
+++ b/netwerk/dns/effective_tld_names.dat
@@ -5519,6 +5519,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/netwerk/ipc/DocumentLoadListener.cpp b/netwerk/ipc/DocumentLoadListener.cpp
index 901ce11b57ca..988ec94a82d4 100644
--- a/netwerk/ipc/DocumentLoadListener.cpp
+++ b/netwerk/ipc/DocumentLoadListener.cpp
@@ -1856,6 +1856,16 @@ DocumentLoadListener::AsyncOnChannelRedirect(
mLoadStateLoadType, nsIWebNavigation::LOAD_FLAGS_ALLOW_MIXED_CONTENT));
}
+ // Like the code above for allowing mixed content, we need to check this here
+ // in case the redirect is not handled in the docshell.
+ nsCOMPtr<nsIURI> oldURI, newURI;
+ aOldChannel->GetURI(getter_AddRefs(oldURI));
+ aNewChannel->GetURI(getter_AddRefs(newURI));
+ if (nsDocShell::IsTorOnionRedirect(oldURI, newURI)) {
+ mLoadStateLoadFlags |=
+ nsDocShell::INTERNAL_LOAD_FLAGS_ALLOW_ONION_URLBAR_REWRITES;
+ }
+
// We need the original URI of the current channel to use to open the real
// channel in the content process. Unfortunately we overwrite the original
// uri of the new channel with the original pre-redirect URI, so grab
diff --git a/toolkit/content/widgets/browser-custom-element.js b/toolkit/content/widgets/browser-custom-element.js
index 62a1ab1d6796..67fa1e5645c0 100644
--- a/toolkit/content/widgets/browser-custom-element.js
+++ b/toolkit/content/widgets/browser-custom-element.js
@@ -261,6 +261,8 @@
this._mayEnableCharacterEncodingMenu = null;
+ this._onionUrlbarRewritesAllowed = false;
+
this._charsetAutodetected = false;
this._contentPrincipal = null;
@@ -686,6 +688,12 @@
}
}
+ get onionUrlbarRewritesAllowed() {
+ return this.isRemoteBrowser
+ ? this._onionUrlbarRewritesAllowed
+ : this.docShell.onionUrlbarRewritesAllowed;
+ }
+
get charsetAutodetected() {
return this.isRemoteBrowser
? this._charsetAutodetected
@@ -1292,7 +1300,8 @@
aInnerWindowID,
aHaveRequestContextID,
aRequestContextID,
- aContentType
+ aContentType,
+ aOnionUrlbarRewritesAllowed
) {
if (this.isRemoteBrowser && this.messageManager) {
if (aCharset != null) {
@@ -1316,6 +1325,7 @@
this._contentRequestContextID = aHaveRequestContextID
? aRequestContextID
: null;
+ this._onionUrlbarRewritesAllowed = aOnionUrlbarRewritesAllowed;
}
}
@@ -1708,6 +1718,7 @@
"_contentStoragePrincipal",
"_isSyntheticDocument",
"_innerWindowID",
+ "_onionUrlbarRewritesAllowed",
]
);
}
diff --git a/toolkit/modules/sessionstore/SessionHistory.jsm b/toolkit/modules/sessionstore/SessionHistory.jsm
index 6c16ac331659..cc47f437824f 100644
--- a/toolkit/modules/sessionstore/SessionHistory.jsm
+++ b/toolkit/modules/sessionstore/SessionHistory.jsm
@@ -318,6 +318,7 @@ var SessionHistoryInternal = {
}
entry.persist = shEntry.persist;
+ entry.onionUrlbarRewritesAllowed = shEntry.onionUrlbarRewritesAllowed;
return entry;
},
@@ -601,6 +602,10 @@ var SessionHistoryInternal = {
}
}
+ if (entry.onionUrlbarRewritesAllowed) {
+ shEntry.onionUrlbarRewritesAllowed = entry.onionUrlbarRewritesAllowed;
+ }
+
return shEntry;
},
1
0

[tor-browser/tor-browser-78.11.0esr-10.5-1] Bug 40073: Disable remote Public Suffix List fetching
by sysrqb@torproject.org 02 Jun '21
by sysrqb@torproject.org 02 Jun '21
02 Jun '21
commit ea45274938a2c348a910ca39a24d8540760d715f
Author: Alex Catarineu <acat(a)torproject.org>
Date: Thu Aug 13 11:05:03 2020 +0200
Bug 40073: Disable remote Public Suffix List fetching
In https://bugzilla.mozilla.org/show_bug.cgi?id=1563246 Firefox implemented
fetching the Public Suffix List via RemoteSettings and replacing the default
one at runtime, which we do not want.
---
browser/components/BrowserGlue.jsm | 5 -----
1 file changed, 5 deletions(-)
diff --git a/browser/components/BrowserGlue.jsm b/browser/components/BrowserGlue.jsm
index e08e461a27ff..ec38d0ca8b33 100644
--- a/browser/components/BrowserGlue.jsm
+++ b/browser/components/BrowserGlue.jsm
@@ -695,7 +695,6 @@ XPCOMUtils.defineLazyModuleGetters(this, {
PluralForm: "resource://gre/modules/PluralForm.jsm",
PrivateBrowsingUtils: "resource://gre/modules/PrivateBrowsingUtils.jsm",
ProcessHangMonitor: "resource:///modules/ProcessHangMonitor.jsm",
- PublicSuffixList: "resource://gre/modules/netwerk-dns/PublicSuffixList.jsm",
RemoteSettings: "resource://services-settings/remote-settings.js",
RemoteSecuritySettings:
"resource://gre/modules/psm/RemoteSecuritySettings.jsm",
@@ -2575,10 +2574,6 @@ BrowserGlue.prototype = {
this._addBreachesSyncHandler();
},
- () => {
- PublicSuffixList.init();
- },
-
() => {
RemoteSecuritySettings.init();
},
1
0

[tor-browser/tor-browser-78.11.0esr-10.5-1] Bug 40025: Remove Mozilla add-on install permissions
by sysrqb@torproject.org 02 Jun '21
by sysrqb@torproject.org 02 Jun '21
02 Jun '21
commit 60e60bd7ba1412c3dd653140cb51fc4c6aa191fb
Author: Alex Catarineu <acat(a)torproject.org>
Date: Mon Jul 27 18:12:55 2020 +0200
Bug 40025: Remove Mozilla add-on install permissions
---
browser/app/permissions | 6 ------
1 file changed, 6 deletions(-)
diff --git a/browser/app/permissions b/browser/app/permissions
index da6b6728043d..5c4c302f5ba5 100644
--- a/browser/app/permissions
+++ b/browser/app/permissions
@@ -11,12 +11,6 @@
origin uitour 1 https://3g2upl4pq6kufc4m.onion
origin uitour 1 about:tor
-# XPInstall
-origin install 1 https://addons.mozilla.org
-
# Remote troubleshooting
origin remote-troubleshooting 1 https://support.mozilla.org
-# addon install
-origin install 1 https://private-network.firefox.com
-origin install 1 https://fpn.firefox.com
1
0