tbb-commits
Threads by month
- ----- 2026 -----
- March
- February
- January
- ----- 2025 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- 1 participants
- 20073 discussions
[tor-browser/tor-browser-78.12.0esr-11.0-1] TB4: Tor Browser's Firefox preference overrides.
by boklm@torproject.org 14 Jul '21
by boklm@torproject.org 14 Jul '21
14 Jul '21
commit ee04b5d1befc0cab4a58619cfe64794d89532095
Author: Mike Perry <mikeperry-git(a)torproject.org>
Date: Tue Sep 10 18:20:43 2013 -0700
TB4: Tor Browser's Firefox preference overrides.
This hack directly includes our preference changes in omni.ja.
Bug 18292: Staged updates fail on Windows
Temporarily disable staged updates on Windows.
Bug 18297: Use separate Noto JP,KR,SC,TC fonts
Bug 23404: Add Noto Sans Buginese to the macOS whitelist
Bug 23745: Set dom.indexedDB.enabled = true
Bug 13575: Disable randomised Firefox HTTP cache decay user tests.
(Fernando Fernandez Mancera <ffmancera(a)riseup.net>)
Bug 17252: Enable session identifiers with FPI
Session tickets and session identifiers were isolated
by OriginAttributes, so we can re-enable them by
allowing the default value (true) of
"security.ssl.disable_session_identifiers".
The pref "security.enable_tls_session_tickets" is obsolete
(removed in https://bugzilla.mozilla.org/917049)
Bug 14952: Enable http/2 and AltSvc
In Firefox, SPDY/HTTP2 now uses Origin Attributes for
isolation of connections, push streams, origin frames, etc.
That means we get first-party isolation provided
"privacy.firstparty.isolate" is true. So in this patch, we
stop overriding "network.http.spdy.enabled" and
"network.http.spdy.enabled.http2".
Alternate Services also use Origin Attributes for isolation.
So we stop overriding
"network.http.altsvc.enabled" and "network.http.altsvc.oe"
as well.
(All 4 of the abovementioned "network.http.*" prefs adopt
Firefox 60ESR's default value of true.)
However, we want to disable HTTP/2 push for now, so we
set "network.http.spdy.allow-push" to false.
"network.http.spdy.enabled.http2draft" was removed in Bug 1132357.
"network.http.sped.enabled.v2" was removed in Bug 912550.
"network.http.sped.enabled.v3" was removed in Bug 1097944.
"network.http.sped.enabled.v3-1" was removed in Bug 1248197.
Bug 26114: addons.mozilla.org is not special
* Don't expose navigator.mozAddonManager on any site
* Don't block NoScript from modifying addons.mozilla.org or other sites
Enable ReaderView mode again (#27281).
Bug 29916: Make sure enterprise policies are disabled
Bug 2874: Block Components.interfaces from content
Bug 26146: Spoof HTTP User-Agent header for desktop platforms
In Tor Browser 8.0, the OS was revealed in both the HTTP User-Agent
header and to JavaScript code via navigator.userAgent. To avoid
leaking the OS inside each HTTP request (which many web servers
log), always use the Windows 7 OS value in the desktop User-Agent
header. We continue to allow access to the actual OS via JavaScript,
since doing so improves compatibility with web applications such
as GitHub and Google Docs.
Bug 12885: Windows Jump Lists fail for Tor Browser
Jumplist entries are stored in a binary file in:
%APPDATA%\\Microsoft\Windows\Recent\CustomDestinations\
and has a name in the form
[a-f0-9]+.customDestinations-ms
The hex at the front is unique per app, and is ultimately derived from
something called the 'App User Model ID' (AUMID) via some unknown
hashing method. The AUMID is provided as a key when programmatically
creating, updating, and deleting a jumplist. The default behaviour in
firefox is for the installer to define an AUMID for an app, and save it
in the registry so that the jumplist data can be removed by the
uninstaller.
However, the Tor Browser does not set this (or any other) regkey during
installation, so this codepath fails and the app's AUMID is left
undefined. As a result the app's AUMID ends up being defined by
windows, but unknowable by Tor Browser. This unknown AUMID is used to
create and modify the jumplist, but the delete API requires that we
provide the app's AUMID explicitly. Since we don't know what the AUMID
is (since the expected regkey where it is normally stored does not
exist) jumplist deletion will fail and we will leave behind a mostly
empty customDestinations-ms file. The name of the file is derived from
the binary path, so an enterprising person could reverse engineer how
that hex name is calculated, and generate the name for Tor Browser's
default Desktop installation path to determine whether a person had
used Tor Browser in the past.
The 'taskbar.grouping.useprofile' option that is enabled by this patch
works around this AUMID problem by having firefox.exe create it's own
AUMID based on the profile path (rather than looking for a regkey). This
way, if a user goes in and enables and disables jumplist entries, the
backing store is properly deleted.
Unfortunately, all windows users currently have this file lurking in
the above mentioned directory and this patch will not remove it since it
was created with an unknown AUMID. However, another patch could be
written which goes to that directory and deletes any item containing the
'Tor Browser' string. See bug 28996.
Bug 31396: Disable indexedDB WebExtension storage backend.
Bug 30845: Make sure default themes and other internal extensions are enabled
Bug 28896: Enable extensions in private browsing by default
Bug 31065: Explicitly allow proxying localhost
Bug 31598: Enable letterboxing
Disable Presentation API everywhere
Bug 21549 - Use Firefox's WASM default pref. It is disabled at safer
security levels.
Bug 32321: Disable Mozilla's MitM pings
Bug 19890: Disable installation of system addons
By setting the URL to "" we make sure that already installed system
addons get deleted as well.
Bug 22548: Firefox downgrades VP9 videos to VP8.
On systems where H.264 is not available or no HWA, VP9 is preferred. But in Tor
Browser 7.0 all youtube videos are degraded to VP8.
This behaviour can be turned off by setting media.benchmark.vp9.threshold to 0.
All clients will get better experience and lower traffic, beause TBB doesn't
use "Use hardware acceleration when available".
Bug 25741 - TBA: Add mobile-override of 000-tor-browser prefs
Bug 16441: Suppress "Reset Tor Browser" prompt.
Bug 29120: Use the in-memory media cache and increase its maximum size.
Bug 33697: use old search config based on list.json
Bug 33855: Ensure that site-specific browser mode is disabled.
Bug 30682: Disable Intermediate CA Preloading.
Bug 40061: Omit the Windows default browser agent from the build
Bug 40140: Videos stop working with Tor Browser 10.0 on Windows
Bug 40322: Consider disabling network.connectivity-service.enabled
Bug 40408: Disallow SVG Context Paint in all web content
---
.eslintignore | 3 +
browser/app/profile/000-tor-browser.js | 646 ++++++++++++++++++++++++++
browser/app/profile/firefox.js | 6 +-
browser/installer/package-manifest.in | 1 +
browser/moz.build | 1 +
mobile/android/app/000-tor-browser-android.js | 47 ++
mobile/android/app/geckoview-prefs.js | 2 +
mobile/android/app/mobile.js | 4 +
mobile/android/app/moz.build | 1 +
taskcluster/ci/source-test/mozlint.yml | 2 +
10 files changed, 710 insertions(+), 3 deletions(-)
diff --git a/.eslintignore b/.eslintignore
index e0be1073894c..031ff26f1808 100644
--- a/.eslintignore
+++ b/.eslintignore
@@ -143,6 +143,9 @@ js/src/jsapi-tests/binast/
js/src/tests/
js/src/Y.js
+# uses `#include`
+mobile/android/app/000-tor-browser-android.js
+
# Uses `#filter substitution`
mobile/android/app/mobile.js
mobile/android/app/geckoview-prefs.js
diff --git a/browser/app/profile/000-tor-browser.js b/browser/app/profile/000-tor-browser.js
new file mode 100644
index 000000000000..3b3bbfd1889b
--- /dev/null
+++ b/browser/app/profile/000-tor-browser.js
@@ -0,0 +1,646 @@
+# Default Preferences
+# Tor Browser Bundle
+# Do not edit this file.
+
+// Please maintain unit tests at ./tbb-tests/browser_tor_TB4.js
+
+// Disable initial homepage notifications
+pref("browser.search.update", false);
+pref("browser.rights.3.shown", true);
+pref("browser.startup.homepage_override.mstone", "ignore");
+pref("startup.homepage_welcome_url", "");
+pref("startup.homepage_welcome_url.additional", "");
+
+// Set a generic, default URL that will be opened in a tab after an update.
+// Typically, this will not be used; instead, the <update> element within
+// each update manifest should contain attributes similar to:
+// actions="showURL"
+// openURL="https://blog.torproject.org/tor-browser-55a2-released"
+pref("startup.homepage_override_url", "https://blog.torproject.org/category/tags/tor-browser");
+
+// Try to nag a bit more about updates: Pop up a restart dialog an hour after the initial dialog
+pref("app.update.promptWaitTime", 3600);
+
+#ifdef XP_WIN
+// For now, disable staged updates on Windows (see #18292).
+pref("app.update.staging.enabled", false);
+#endif
+
+// Disable "Slow startup" warnings and associated disk history
+// (bug #13346)
+pref("browser.slowStartup.notificationDisabled", true);
+pref("browser.slowStartup.maxSamples", 0);
+pref("browser.slowStartup.samples", 0);
+
+// Disable the "Refresh" prompt that is displayed for stale profiles.
+pref("browser.disableResetPrompt", true);
+
+// Disk activity: Disable Browsing History Storage
+pref("browser.privatebrowsing.autostart", true);
+pref("browser.cache.disk.enable", false);
+pref("browser.cache.offline.enable", false);
+pref("permissions.memory_only", true);
+pref("network.cookie.lifetimePolicy", 2);
+pref("security.nocertdb", true);
+
+// Disk activity: TBB Directory Isolation
+pref("browser.download.useDownloadDir", false);
+pref("browser.shell.checkDefaultBrowser", false);
+pref("browser.download.manager.addToRecentDocs", false);
+
+// Misc privacy: Disk
+pref("signon.rememberSignons", false);
+pref("browser.formfill.enable", false);
+pref("signon.autofillForms", false);
+pref("browser.sessionstore.privacy_level", 2);
+// Use the in-memory media cache and increase its maximum size (#29120)
+pref("browser.privatebrowsing.forceMediaMemoryCache", true);
+pref("media.memory_cache_max_size", 16384);
+// Disable site-specific browsing to avoid sharing site icons with the OS.
+pref("browser.ssb.enabled", false);
+
+// Misc privacy: Remote
+pref("browser.send_pings", false);
+pref("geo.enabled", false);
+pref("geo.provider.network.url", "");
+pref("browser.search.suggest.enabled", false);
+pref("browser.safebrowsing.malware.enabled", false);
+pref("browser.safebrowsing.phishing.enabled", false);
+pref("browser.safebrowsing.downloads.enabled", false);
+pref("browser.safebrowsing.downloads.remote.enabled", false);
+pref("browser.safebrowsing.blockedURIs.enabled", false);
+pref("browser.safebrowsing.downloads.remote.url", "");
+pref("browser.safebrowsing.provider.google.updateURL", "");
+pref("browser.safebrowsing.provider.google.gethashURL", "");
+pref("browser.safebrowsing.provider.google4.updateURL", "");
+pref("browser.safebrowsing.provider.google4.gethashURL", "");
+pref("browser.safebrowsing.provider.mozilla.updateURL", "");
+pref("browser.safebrowsing.provider.mozilla.gethashURL", "");
+pref("extensions.ui.lastCategory", "addons://list/extension");
+pref("datareporting.healthreport.uploadEnabled", false);
+pref("datareporting.policy.dataSubmissionEnabled", false);
+// Make sure Unified Telemetry is really disabled, see: #18738.
+pref("toolkit.telemetry.unified", false);
+pref("toolkit.telemetry.enabled", false);
+#ifdef XP_WIN
+// Defense-in-depth: ensure that the Windows default browser agent will
+// not ping Mozilla if it is somehow present (we omit it at build time).
+pref("default-browser-agent.enabled", false);
+#endif
+pref("identity.fxaccounts.enabled", false); // Disable sync by default
+pref("services.sync.engine.prefs", false); // Never sync prefs, addons, or tabs with other browsers
+pref("services.sync.engine.addons", false);
+pref("services.sync.engine.tabs", false);
+pref("extensions.getAddons.cache.enabled", false); // https://blog.mozilla.org/addons/how-to-opt-out-of-add-on-metadata-updates/
+pref("browser.newtabpage.enabled", false);
+pref("browser.search.region", "US"); // The next two prefs disable GeoIP search lookups (#16254)
+pref("browser.search.geoip.url", "");
+pref("browser.fixup.alternate.enabled", false); // Bug #16783: Prevent .onion fixups
+// Make sure there is no Tracking Protection active in Tor Browser, see: #17898.
+pref("privacy.trackingprotection.enabled", false);
+pref("privacy.trackingprotection.pbmode.enabled", false);
+pref("privacy.trackingprotection.annotate_channels", false);
+pref("privacy.trackingprotection.cryptomining.enabled", false);
+pref("privacy.trackingprotection.fingerprinting.enabled", false);
+pref("privacy.trackingprotection.socialtracking.enabled", false);
+pref("privacy.socialtracking.block_cookies.enabled", false);
+pref("privacy.annotate_channels.strict_list.enabled", false);
+
+// Disable the Pocket extension (Bug #18886 and #31602)
+pref("extensions.pocket.enabled", false);
+pref("network.http.referer.hideOnionSource", true);
+
+// Disable use of WiFi location information
+pref("browser.region.network.scan", false);
+pref("browser.region.network.url", "");
+
+// Don't load Mozilla domains in a separate tab process
+pref("browser.tabs.remote.separatedMozillaDomains", "");
+
+// Avoid DNS lookups on search terms
+pref("browser.urlbar.dnsResolveSingleWordsAfterSearch", 0);
+
+// Disable about:newtab and "first run" experiments
+pref("messaging-system.rsexperimentloader.enabled", false);
+pref("trailhead.firstrun.branches", "");
+
+// Clear the list of trusted recursive resolver services
+pref("network.trr.resolvers", "");
+
+// Disable crlite
+pref("security.pki.crlite_mode", 0);
+
+// Disable website password breach alerts
+pref("signon.management.page.breach-alerts.enabled", false);
+pref("extensions.fxmonitor.enabled", false);
+
+// Remove mobile app tracking URLs
+pref("signon.management.page.mobileAndroidURL", "");
+pref("signon.management.page.mobileAppleURL", "");
+
+// Disable ServiceWorkers and push notifications by default
+pref("dom.serviceWorkers.enabled", false);
+pref("dom.push.enabled", false);
+
+// Fingerprinting
+pref("webgl.disable-extensions", true);
+pref("webgl.disable-fail-if-major-performance-caveat", true);
+pref("webgl.enable-webgl2", false);
+pref("gfx.downloadable_fonts.fallback_delay", -1);
+pref("browser.startup.homepage_override.buildID", "20100101");
+pref("browser.link.open_newwindow.restriction", 0); // Bug 9881: Open popups in new tabs (to avoid fullscreen popups)
+// Set video VP9 to 0 for everyone (bug 22548)
+pref("media.benchmark.vp9.threshold", 0);
+pref("dom.enable_resource_timing", false); // Bug 13024: To hell with this API
+pref("privacy.resistFingerprinting", true);
+pref("privacy.resistFingerprinting.block_mozAddonManager", true); // Bug 26114
+pref("dom.webaudio.enabled", false); // Bug 13017: Disable Web Audio API
+pref("dom.w3c_touch_events.enabled", 0); // Bug 10286: Always disable Touch API
+pref("dom.w3c_pointer_events.enabled", false);
+pref("dom.vr.enabled", false); // Bug 21607: Disable WebVR for now
+// Disable randomised Firefox HTTP cache decay user test groups (Bug: 13575)
+pref("security.webauth.webauthn", false); // Bug 26614: Disable Web Authentication API for now
+// Disable intermediate preloading (Bug 30682)
+pref("security.remote_settings.intermediates.enabled", false);
+// Bug 2874: Block Components.interfaces from content
+pref("dom.use_components_shim", false);
+// Enable letterboxing
+pref("privacy.resistFingerprinting.letterboxing", true);
+// Disable network information API everywhere. It gets spoofed in bug 1372072
+// but, alas, the behavior is inconsistent across platforms, see:
+// https://trac.torproject.org/projects/tor/ticket/27268#comment:19. We should
+// not leak that difference if possible.
+pref("dom.netinfo.enabled", false);
+pref("network.http.referer.defaultPolicy", 2); // Bug 32948: Make referer behavior consistent regardless of private browing mode status
+pref("media.videocontrols.picture-in-picture.enabled", false); // Bug 40148: disable until audited in #40147
+
+// Third party stuff
+pref("privacy.firstparty.isolate", true); // Always enforce first party isolation
+pref("network.cookie.cookieBehavior", 1);
+pref("network.http.spdy.allow-push", false); // Disabled for now. See https://bugs.torproject.org/27127
+pref("network.predictor.enabled", false); // Temporarily disabled. See https://bugs.torproject.org/16633
+
+// Proxy and proxy security
+pref("network.proxy.socks", "127.0.0.1");
+pref("network.proxy.socks_port", 9150);
+pref("network.proxy.socks_remote_dns", true);
+pref("network.proxy.no_proxies_on", ""); // For fingerprinting and local service vulns (#10419)
+pref("network.proxy.allow_hijacking_localhost", true); // Allow proxies for localhost (#31065)
+pref("network.proxy.type", 1);
+pref("network.security.ports.banned", "9050,9051,9150,9151");
+pref("network.dns.disabled", true); // This should cover the #5741 patch for DNS leaks
+pref("network.dns.disablePrefetch", true);
+pref("network.protocol-handler.external-default", false);
+pref("network.protocol-handler.external.mailto", false);
+pref("network.protocol-handler.external.news", false);
+pref("network.protocol-handler.external.nntp", false);
+pref("network.protocol-handler.external.snews", false);
+pref("network.protocol-handler.warn-external.mailto", true);
+pref("network.protocol-handler.warn-external.news", true);
+pref("network.protocol-handler.warn-external.nntp", true);
+pref("network.protocol-handler.warn-external.snews", true);
+// Make sure we don't have any GIO supported protocols (defense in depth
+// measure)
+pref("network.gio.supported-protocols", "");
+pref("plugin.disable", true); // Disable to search plugins on first start
+pref("plugin.state.flash", 0); // Disable for defense-in-depth
+pref("media.peerconnection.enabled", false); // Disable WebRTC interfaces
+// Disables media devices but only if `media.peerconnection.enabled` is set to
+// `false` as well. (see bug 16328 for this defense-in-depth measure)
+pref("media.navigator.enabled", false);
+// GMPs: We make sure they don't show up on the Add-on panel and confuse users.
+// And the external update/donwload server must not get pinged. We apply a
+// clever solution for https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=769716.
+pref("media.gmp-provider.enabled", false);
+pref("media.gmp-manager.url.override", "data:text/plain,");
+// Since ESR52 it is not enough anymore to block pinging the GMP update/download
+// server. There is a local fallback that must be blocked now as well. See:
+// https://bugzilla.mozilla.org/show_bug.cgi?id=1267495.
+pref("media.gmp-manager.updateEnabled", false);
+// Mozilla is relying on preferences to make sure no DRM blob is downloaded and
+// run. Even though those prefs should be set correctly by specifying
+// --disable-eme (which we do), we disable all of them here as well for defense
+// in depth (see bug 16285 for more details).
+pref("browser.eme.ui.enabled", false);
+pref("media.gmp-widevinecdm.visible", false);
+pref("media.gmp-widevinecdm.enabled", false);
+pref("media.eme.enabled", false);
+pref("media.mediadrm-widevinecdm.visible", false);
+// WebIDE can bypass proxy settings for remote debugging. It also downloads
+// some additional addons that we have not reviewed. Turn all that off.
+pref("devtools.webide.autoinstallADBExtension", false);
+pref("devtools.webide.enabled", false);
+// The in-browser debugger for debugging chrome code is not coping with our
+// restrictive DNS look-up policy. We use "127.0.0.1" instead of "localhost" as
+// a workaround. See bug 16523 for more details.
+pref("devtools.debugger.chrome-debugging-host", "127.0.0.1");
+// Disable using UNC paths (bug 26424 and Mozilla's bug 1413868)
+pref("network.file.disable_unc_paths", true);
+// Enhance our treatment of file:// to avoid proxy bypasses (see Mozilla's bug
+// 1412081)
+pref("network.file.path_blacklist", "/net");
+// Make sure no enterprise policy can interfere with our proxy settings, see
+// #29916.
+pref("browser.policies.testing.disallowEnterprise", true);
+
+// Security slider
+pref("svg.in-content.enabled", true);
+pref("mathml.disabled", false);
+
+// Bug 40408
+pref("svg.context-properties.content.allowed-domains", "");
+
+// Network and performance
+pref("security.ssl.enable_false_start", true);
+pref("network.http.connection-retry-timeout", 0);
+pref("network.http.max-persistent-connections-per-proxy", 256);
+pref("network.manage-offline-status", false);
+// No need to leak things to Mozilla, see bug 21790 and tor-browser#40322
+pref("network.captive-portal-service.enabled", false);
+pref("network.connectivity-service.enabled", false);
+// As a "defense in depth" measure, configure an empty push server URL (the
+// DOM Push features are disabled by default via other prefs).
+pref("dom.push.serverURL", "");
+
+// Extension support
+pref("extensions.autoDisableScopes", 0);
+pref("extensions.bootstrappedAddons", "{}");
+pref("extensions.checkCompatibility.4.*", false);
+pref("extensions.databaseSchema", 3);
+pref("extensions.enabledAddons", "https-everywhere%40eff.org:3.1.4,%7B73a6fe31-595d-460b-a920-fcc0f8843232%7D:2.6.6.1,torbutton%40torproject.org:1.5.2,ubufox%40ubuntu.com:2.6,%7B972ce4c6-7e08-4474-a285-3208198ce6fd%7D:17.0.5");
+pref("extensions.enabledItems", "langpack-en-US@firefox.mozilla.org:,{73a6fe31-595d-460b-a920-fcc0f8843232}:1.9.9.57,{e0204bd5-9d31-402b-a99d-a6aa8ffebdca}:1.2.4,{972ce4c6-7e08-4474-a285-3208198ce6fd}:3.5.8");
+pref("extensions.enabledScopes", 5); // AddonManager.SCOPE_PROFILE=1 | AddonManager.SCOPE_APPLICATION=4
+pref("extensions.pendingOperations", false);
+pref("xpinstall.whitelist.add", "");
+pref("xpinstall.whitelist.add.36", "");
+// We don't know what extensions Mozilla is advertising to our users and we
+// don't want to have some random Google Analytics script running either on the
+// about:addons page, see bug 22073, 22900 and 31601.
+pref("extensions.getAddons.showPane", false);
+pref("extensions.htmlaboutaddons.recommendations.enabled", false);
+// Show our legacy extensions directly on about:addons and get rid of the
+// warning for the default theme.
+pref("extensions.legacy.exceptions", "{972ce4c6-7e08-4474-a285-3208198ce6fd},torbutton(a)torproject.org");
+// Bug 26114: Allow NoScript to access addons.mozilla.org etc.
+pref("extensions.webextensions.restrictedDomains", "");
+// Bug 28896: Make sure our bundled WebExtensions are running in Private Browsing Mode
+pref("extensions.allowPrivateBrowsingByDefault", true);
+
+// Toolbar layout
+pref("browser.uiCustomization.state", "{\"placements\":{\"widget-overflow-fixed-list\":[],\"PersonalToolbar\":[\"personal-bookmarks\"],\"nav-bar\":[\"back-button\",\"forward-button\",\"stop-reload-button\",\"urlbar-container\",\"torbutton-button\",\"security-level-button\",\"downloads-button\"],\"TabsToolbar\":[\"tabbrowser-tabs\",\"new-tab-button\",\"alltabs-button\"],\"toolbar-menubar\":[\"menubar-items\"],\"PanelUI-contents\":[\"home-button\",\"edit-controls\",\"zoom-controls\",\"new-window-button\",\"save-page-button\",\"print-button\",\"bookmarks-menu-button\",\"history-panelmenu\",\"find-button\",\"preferences-button\",\"add-ons-button\",\"developer-button\"],\"addon-bar\":[\"addonbar-closebutton\",\"status-bar\"]},\"seen\":[\"developer-button\",\"https-everywhere-eff_eff_org-browser-action\",\"_73a6fe31-595d-460b-a920-fcc0f8843232_-browser-action\"],\"dirtyAreaCache\":[\"PersonalToolbar\",\"nav-bar\",\"TabsToolbar\",\"toolbar-menubar\"],\"currentVersion\":14,\"newElementCount
\":1}");
+
+// Putting the search engine prefs into this file to fix #11236.
+// Default search engine
+pref("browser.search.defaultenginename", "Search");
+
+// Search engine order (order displayed in the search bar dropdown)
+// Somewhat surprisingly we get some random behavior if we specify more than
+// two search engines as below. See
+// https://bugzilla.mozilla.org/show_bug.cgi?id=1126722 for details.
+pref("browser.search.order.extra.1", "Search");
+pref("browser.search.order.extra.2", "YouTube");
+
+// Enforce certificate pinning, see: https://bugs.torproject.org/16206
+pref("security.cert_pinning.enforcement_level", 2);
+
+// Don't allow MitM via Microsoft Family Safety, see bug 21686
+pref("security.family_safety.mode", 0);
+
+// Don't allow MitM via enterprise roots, see bug 30681
+pref("security.enterprise_roots.enabled", false);
+
+// Don't ping Mozilla for MitM detection, see bug 32321
+pref("security.certerrors.mitm.priming.enabled", false);
+
+// Disable the language pack signing check for now on macOS, see #31942
+#ifdef XP_MACOSX
+pref("extensions.langpacks.signatures.required", false);
+#endif
+
+// Avoid report TLS errors to Mozilla. We might want to repurpose this feature
+// one day to help detecting bad relays (which is bug 19119). For now we just
+// hide the checkbox, see bug 22072.
+pref("security.ssl.errorReporting.enabled", false);
+
+// Workaround for https://bugs.torproject.org/13579. Progress on
+// `about:downloads` is only shown if the following preference is set to `true`
+// in case the download panel got removed from the toolbar.
+pref("browser.download.panel.shown", true);
+
+// Treat .onions as secure
+pref("dom.securecontext.whitelist_onions", true);
+
+// Disable special URL bar behaviors
+pref("browser.urlbar.suggest.topsites", false);
+pref("browser.urlbar.update1.interventions", false);
+pref("browser.urlbar.update1.searchTips", false);
+
+// Skip checking omni.ja and other files for corruption since the result
+// is only reported via telemetry (which is disabled).
+pref("corroborator.enabled", false);
+
+// Having the RDD Opus option enabled on Windows breaks videos for us.
+// See: https://bugzilla.mozilla.org/show_bug.cgi?id=1667360 and
+// tor-browser#40140.
+#ifdef XP_WIN
+pref("media.rdd-opus.enabled", false);
+#endif
+
+// prefs to disable jump-list entries in the taskbar on Windows (see bug #12885)
+#ifdef XP_WIN
+// this pref changes the app's set AUMID to be dependent on the profile path, rather than
+// attempting to read it from the registry; this is necessary so that the file generated
+// by the jumplist system can be properly deleted if it is disabled
+pref("taskbar.grouping.useprofile", true);
+pref("browser.taskbar.lists.enabled", false);
+pref("browser.taskbar.lists.frequent.enabled", false);
+pref("browser.taskbar.lists.tasks.enabled", false);
+pref("browser.taskbar.lists.recent.enabled", false);
+#endif
+
+// Disable Presentation API
+pref("dom.presentation.controller.enabled", false);
+pref("dom.presentation.enabled", false);
+pref("dom.presentation.discoverable", false);
+pref("dom.presentation.discoverable.encrypted", false);
+pref("dom.presentation.discovery.enabled", false);
+pref("dom.presentation.receiver.enabled", false);
+
+pref("dom.audiochannel.audioCompeting", false);
+pref("dom.audiochannel.mediaControl", false);
+
+#expand pref("torbrowser.version", __TOR_BROWSER_VERSION_QUOTED__);
+
+// Old torbutton prefs
+
+// debug prefs
+pref("extensions.torbutton.loglevel",4);
+pref("extensions.torbutton.logmethod",1); // 0=stdout, 1=errorconsole, 2=debuglog
+
+// Display prefs
+pref("extensions.torbutton.display_circuit", true);
+pref("extensions.torbutton(a)torproject.org.description", "chrome://torbutton/locale/torbutton.properties");
+pref("extensions.torbutton.updateNeeded", false);
+
+// Tor check and proxy prefs
+pref("extensions.torbutton.test_enabled",true);
+pref("extensions.torbutton.test_url","https://check.torproject.org/?TorButton=true");
+pref("extensions.torbutton.local_tor_check",true);
+pref("extensions.torbutton.versioncheck_url","https://www.torproject.org/projects/torbrowser/RecommendedTBBVersions");
+pref("extensions.torbutton.versioncheck_enabled",true);
+pref("extensions.torbutton.use_nontor_proxy",false);
+
+// State prefs:
+pref("extensions.torbutton.startup",false);
+pref("extensions.torbutton.inserted_button",false);
+pref("extensions.torbutton.inserted_security_level",false);
+
+// This is only used when letterboxing is disabled.
+// See #7255 for details. We display the warning three times to make sure the
+// user did not click on it by accident.
+pref("extensions.torbutton.maximize_warnings_remaining", 3);
+
+// Security prefs:
+pref("extensions.torbutton.clear_http_auth",true);
+pref("extensions.torbutton.close_newnym",true);
+pref("extensions.torbutton.resize_new_windows",false);
+pref("extensions.torbutton.startup_state", 2); // 0=non-tor, 1=tor, 2=last
+pref("extensions.torbutton.tor_memory_jar",false);
+pref("extensions.torbutton.nontor_memory_jar",false);
+pref("extensions.torbutton.launch_warning",true);
+
+// Opt out of Firefox addon pings:
+// https://developer.mozilla.org/en/Addons/Working_with_AMO
+pref("extensions.torbutton(a)torproject.org.getAddons.cache.enabled", false);
+
+// Security Slider
+pref("extensions.torbutton.security_slider", 4);
+pref("extensions.torbutton.security_custom", false);
+
+pref("extensions.torbutton.confirm_plugins", true);
+pref("extensions.torbutton.confirm_newnym", true);
+
+pref("extensions.torbutton.noscript_inited", false);
+pref("extensions.torbutton.noscript_persist", false);
+
+// Browser home page:
+pref("browser.startup.homepage", "about:tor");
+
+// This pref specifies an ad-hoc "version" for various pref update hacks we need to do
+pref("extensions.torbutton.pref_fixup_version", 0);
+
+// If we are bundling fonts, whitelist those bundled fonts, and restrict system fonts to a selection.
+
+#ifdef MOZ_BUNDLED_FONTS
+
+#ifdef XP_MACOSX
+pref("font.system.whitelist", "AppleGothic, Apple Color Emoji, Arial, Courier, Geneva, Georgia, Heiti TC, Helvetica, Helvetica Neue, .Helvetica Neue DeskInterface, Hiragino Kaku Gothic ProN, Lucida Grande, Monaco, Noto Sans Armenian, Noto Sans Bengali, Noto Sans Buginese, Noto Sans Canadian Aboriginal, Noto Sans Cherokee, Noto Sans Devanagari, Noto Sans Ethiopic, Noto Sans Gujarati, Noto Sans Gurmukhi, Noto Sans Kannada, Noto Sans Khmer, Noto Sans Lao, Noto Sans Malayalam, Noto Sans Mongolian, Noto Sans Myanmar, Noto Sans Oriya, Noto Sans Sinhala, Noto Sans Tamil, Noto Sans Telugu, Noto Sans Thaana, Noto Sans Tibetan, Noto Sans Yi, STHeiti, STIX Math, Tahoma, Thonburi, Times, Times New Roman, Verdana");
+pref("font.name-list.cursive.x-unicode", "Apple Chancery, Noto Sans Armenian, Noto Sans Bengali, Noto Sans Buginese, Noto Sans Canadian Aboriginal, Noto Sans Cherokee, Noto Sans Devanagari, Noto Sans Ethiopic, Noto Sans Gujarati, Noto Sans Gurmukhi, Noto Sans Kannada, Noto Sans Khmer, Noto Sans Lao, Noto Sans Malayalam, Noto Sans Mongolian, Noto Sans Myanmar, Noto Sans Oriya, Noto Sans Sinhala, Noto Sans Tamil, Noto Sans Telugu, Noto Sans Thaana, Noto Sans Tibetan, Noto Sans Yi");
+pref("font.name-list.fantasy.x-unicode", "Papyrus, Noto Sans Armenian, Noto Sans Bengali, Noto Sans Buginese, Noto Sans Canadian Aboriginal, Noto Sans Cherokee, Noto Sans Devanagari, Noto Sans Ethiopic, Noto Sans Gujarati, Noto Sans Gurmukhi, Noto Sans Kannada, Noto Sans Khmer, Noto Sans Lao, Noto Sans Malayalam, Noto Sans Mongolian, Noto Sans Myanmar, Noto Sans Oriya, Noto Sans Sinhala, Noto Sans Tamil, Noto Sans Telugu, Noto Sans Thaana, Noto Sans Tibetan, Noto Sans Yi");
+pref("font.name-list.monospace.x-unicode", "Courier, Arial, Noto Sans Armenian, Noto Sans Bengali, Noto Sans Buginese, Noto Sans Canadian Aboriginal, Noto Sans Cherokee, Noto Sans Devanagari, Noto Sans Ethiopic, Noto Sans Gujarati, Noto Sans Gurmukhi, Noto Sans Kannada, Noto Sans Khmer, Noto Sans Lao, Noto Sans Malayalam, Noto Sans Mongolian, Noto Sans Myanmar, Noto Sans Oriya, Noto Sans Sinhala, Noto Sans Tamil, Noto Sans Telugu, Noto Sans Thaana, Noto Sans Tibetan, Noto Sans Yi");
+pref("font.name-list.sans-serif.x-unicode", "Helvetica, Tahoma, Arial, Noto Sans Armenian, Noto Sans Bengali, Noto Sans Buginese, Noto Sans Canadian Aboriginal, Noto Sans Cherokee, Noto Sans Devanagari, Noto Sans Ethiopic, Noto Sans Gujarati, Noto Sans Gurmukhi, Noto Sans Kannada, Noto Sans Khmer, Noto Sans Lao, Noto Sans Malayalam, Noto Sans Mongolian, Noto Sans Myanmar, Noto Sans Oriya, Noto Sans Sinhala, Noto Sans Tamil, Noto Sans Telugu, Noto Sans Thaana, Noto Sans Tibetan, Noto Sans Yi");
+pref("font.name-list.serif.x-unicode", "Times, Arial, Noto Sans Armenian, Noto Sans Bengali, Noto Sans Buginese, Noto Sans Canadian Aboriginal, Noto Sans Cherokee, Noto Sans Devanagari, Noto Sans Ethiopic, Noto Sans Gujarati, Noto Sans Gurmukhi, Noto Sans Kannada, Noto Sans Khmer, Noto Sans Lao, Noto Sans Malayalam, Noto Sans Mongolian, Noto Sans Myanmar, Noto Sans Oriya, Noto Sans Sinhala, Noto Sans Tamil, Noto Sans Telugu, Noto Sans Thaana, Noto Sans Tibetan, Noto Sans Yi");
+pref("font.name.cursive.ar", "Arial");
+pref("font.name.fantasy.ar", "Arial");
+pref("font.name.monospace.ar", "Arial");
+pref("font.name.sans-serif.ar", "Arial");
+#endif
+
+#ifdef XP_WIN
+pref("font.system.whitelist", "Arial, Batang, 바탕, Cambria Math, Courier New, Euphemia, Gautami, Georgia, Gulim, 굴림, GulimChe, 굴림체, Iskoola Pota, Kalinga, Kartika, Latha, Lucida Console, MS Gothic, MS ゴシック, MS Mincho, MS 明朝, MS PGothic, MS Pゴシック, MS PMincho, MS P明朝, MV Boli, Malgun Gothic, Mangal, Meiryo, Meiryo UI, Microsoft Himalaya, Microsoft JhengHei, Microsoft JhengHei UI, Microsoft YaHei, 微软雅黑, Microsoft YaHei UI, MingLiU, 細明體, Noto Sans Buginese, Noto Sans Khmer, Noto Sans Lao, Noto Sans Myanmar, Noto Sans Yi, Nyala, PMingLiU, 新細明體, Plantagenet Cherokee, Raavi, Segoe UI, Shruti, SimSun, 宋体, Sylfaen, Tahoma, Times New Roman, Tunga, Verdana, Vrinda, Yu Gothic UI");
+#endif
+
+#ifdef XP_LINUX
+pref("font.default.lo", "Noto Sans Lao");
+pref("font.default.my", "Noto Sans Myanmar");
+pref("font.default.x-western", "sans-serif");
+pref("font.name-list.cursive.ar", "Noto Naskh Arabic, Tinos, Georgia, Noto Serif Armenian, Noto Serif Khmer, Noto Serif Lao, Noto Serif Thai");
+pref("font.name-list.cursive.he", "Noto Sans Hebrew, Tinos, Georgia, Noto Serif Armenian, Noto Serif Khmer, Noto Serif Lao, Noto Serif Thai");
+pref("font.name-list.cursive.x-cyrillic", "Tinos, Georgia, Noto Serif Armenian, Noto Serif Khmer, Noto Serif Lao, Noto Serif Thai");
+pref("font.name-list.cursive.x-unicode", "Tinos, Georgia, Noto Serif Armenian, Noto Serif Khmer, Noto Serif Lao, Noto Serif Thai");
+pref("font.name-list.cursive.x-western", "Tinos, Georgia, Noto Serif Armenian, Noto Serif Khmer, Noto Serif Lao, Noto Serif Thai");
+pref("font.name-list.fantasy.ar", "Noto Naskh Arabic, Tinos, Georgia, Noto Serif Armenian, Noto Serif Khmer, Noto Serif Lao, Noto Serif Thai");
+pref("font.name-list.fantasy.el", "Tinos, Georgia, Noto Serif Armenian, Noto Serif Khmer, Noto Serif Lao, Noto Serif Thai");
+pref("font.name-list.fantasy.he", "Noto Sans Hebrew, Tinos, Georgia, Noto Serif Armenian, Noto Serif Khmer, Noto Serif Lao, Noto Serif Thai");
+pref("font.name-list.fantasy.x-cyrillic", "Tinos, Georgia, Noto Serif Armenian, Noto Serif Khmer, Noto Serif Lao, Noto Serif Thai");
+pref("font.name-list.fantasy.x-unicode", "Tinos, Georgia, Noto Serif Armenian, Noto Serif Khmer, Noto Serif Lao, Noto Serif Thai");
+pref("font.name-list.fantasy.x-western", "Tinos, Georgia, Noto Serif Armenian, Noto Serif Khmer, Noto Serif Lao, Noto Serif Thai");
+pref("font.name-list.monospace.ar", "Noto Naskh Arabic, Cousine, Courier, Courier New, Noto Naskh Arabic, Noto Sans Armenian, Noto Sans Bengali, Noto Sans Buginese, Noto Sans JP Regular, Noto Sans KR Regular, Noto Sans SC Regular, Noto Sans TC Regular, Noto Sans Canadian Aboriginal, Noto Sans Cherokee, Noto Sans Devanagari, Noto Sans Ethiopic, Noto Sans Georgian, Noto Sans Gujarati, Noto Sans Gurmukhi, Noto Sans Hebrew, Noto Sans Kannada, Noto Sans Khmer, Noto Sans Lao, Noto Sans Malayalam, Noto Sans Mongolian, Noto Sans Myanmar, Noto Sans Oriya, Noto Sans Sinhala, Noto Sans Tamil, Noto Sans Telugu, Noto Sans Thaana, Noto Sans Thai, Noto Sans Tibetan, Noto Sans Yi, Noto Serif Armenian, Noto Serif Khmer, Noto Serif Lao, Noto Serif Thai");
+pref("font.name-list.monospace.el", "Cousine, Courier, Courier New, Noto Naskh Arabic, Noto Sans Armenian, Noto Sans Bengali, Noto Sans Buginese, Noto Sans JP Regular, Noto Sans KR Regular, Noto Sans SC Regular, Noto Sans TC Regular, Noto Sans Canadian Aboriginal, Noto Sans Cherokee, Noto Sans Devanagari, Noto Sans Ethiopic, Noto Sans Georgian, Noto Sans Gujarati, Noto Sans Gurmukhi, Noto Sans Hebrew, Noto Sans Kannada, Noto Sans Khmer, Noto Sans Lao, Noto Sans Malayalam, Noto Sans Mongolian, Noto Sans Myanmar, Noto Sans Oriya, Noto Sans Sinhala, Noto Sans Tamil, Noto Sans Telugu, Noto Sans Thaana, Noto Sans Thai, Noto Sans Tibetan, Noto Sans Yi, Noto Serif Armenian, Noto Serif Khmer, Noto Serif Lao, Noto Serif Thai");
+pref("font.name-list.monospace.he", "Noto Sans Hebrew, Cousine, Courier, Courier New, Noto Naskh Arabic, Noto Sans Armenian, Noto Sans Bengali, Noto Sans Buginese, Noto Sans JP Regular, Noto Sans KR Regular, Noto Sans SC Regular, Noto Sans TC Regular, Noto Sans Canadian Aboriginal, Noto Sans Cherokee, Noto Sans Devanagari, Noto Sans Ethiopic, Noto Sans Georgian, Noto Sans Gujarati, Noto Sans Gurmukhi, Noto Sans Hebrew, Noto Sans Kannada, Noto Sans Khmer, Noto Sans Lao, Noto Sans Malayalam, Noto Sans Mongolian, Noto Sans Myanmar, Noto Sans Oriya, Noto Sans Sinhala, Noto Sans Tamil, Noto Sans Telugu, Noto Sans Thaana, Noto Sans Thai, Noto Sans Tibetan, Noto Sans Yi, Noto Serif Armenian, Noto Serif Khmer, Noto Serif Lao, Noto Serif Thai");
+pref("font.name-list.monospace.ja", "Noto Sans JP Regular, Cousine, Courier, Courier New, Noto Naskh Arabic, Noto Sans Armenian, Noto Sans Bengali, Noto Sans Buginese, Noto Sans JP Regular, Noto Sans KR Regular, Noto Sans SC Regular, Noto Sans TC Regular, Noto Sans Canadian Aboriginal, Noto Sans Cherokee, Noto Sans Devanagari, Noto Sans Ethiopic, Noto Sans Georgian, Noto Sans Gujarati, Noto Sans Gurmukhi, Noto Sans Hebrew, Noto Sans Kannada, Noto Sans Khmer, Noto Sans Lao, Noto Sans Malayalam, Noto Sans Mongolian, Noto Sans Myanmar, Noto Sans Oriya, Noto Sans Sinhala, Noto Sans Tamil, Noto Sans Telugu, Noto Sans Thaana, Noto Sans Thai, Noto Sans Tibetan, Noto Sans Yi, Noto Serif Armenian, Noto Serif Khmer, Noto Serif Lao, Noto Serif Thai");
+pref("font.name-list.monospace.ko", "Noto Sans KR Regular, Cousine, Courier, Courier New, Noto Naskh Arabic, Noto Sans Armenian, Noto Sans Bengali, Noto Sans Buginese, Noto Sans JP Regular, Noto Sans KR Regular, Noto Sans SC Regular, Noto Sans TC Regular, Noto Sans Canadian Aboriginal, Noto Sans Cherokee, Noto Sans Devanagari, Noto Sans Ethiopic, Noto Sans Georgian, Noto Sans Gujarati, Noto Sans Gurmukhi, Noto Sans Hebrew, Noto Sans Kannada, Noto Sans Khmer, Noto Sans Lao, Noto Sans Malayalam, Noto Sans Mongolian, Noto Sans Myanmar, Noto Sans Oriya, Noto Sans Sinhala, Noto Sans Tamil, Noto Sans Telugu, Noto Sans Thaana, Noto Sans Thai, Noto Sans Tibetan, Noto Sans Yi, Noto Serif Armenian, Noto Serif Khmer, Noto Serif Lao, Noto Serif Thai");
+pref("font.name-list.monospace.th", "Noto Sans Thai, Cousine, Courier, Courier New, Noto Naskh Arabic, Noto Sans Armenian, Noto Sans Bengali, Noto Sans Buginese, Noto Sans JP Regular, Noto Sans KR Regular, Noto Sans SC Regular, Noto Sans TC Regular, Noto Sans Canadian Aboriginal, Noto Sans Cherokee, Noto Sans Devanagari, Noto Sans Ethiopic, Noto Sans Georgian, Noto Sans Gujarati, Noto Sans Gurmukhi, Noto Sans Hebrew, Noto Sans Kannada, Noto Sans Khmer, Noto Sans Lao, Noto Sans Malayalam, Noto Sans Mongolian, Noto Sans Myanmar, Noto Sans Oriya, Noto Sans Sinhala, Noto Sans Tamil, Noto Sans Telugu, Noto Sans Thaana, Noto Sans Thai, Noto Sans Tibetan, Noto Sans Yi, Noto Serif Armenian, Noto Serif Khmer, Noto Serif Lao, Noto Serif Thai");
+pref("font.name-list.monospace.x-armn", "Noto Sans Armenian, Cousine, Courier, Courier New, Noto Naskh Arabic, Noto Sans Armenian, Noto Sans Bengali, Noto Sans Buginese, Noto Sans JP Regular, Noto Sans KR Regular, Noto Sans SC Regular, Noto Sans TC Regular, Noto Sans Canadian Aboriginal, Noto Sans Cherokee, Noto Sans Devanagari, Noto Sans Ethiopic, Noto Sans Georgian, Noto Sans Gujarati, Noto Sans Gurmukhi, Noto Sans Hebrew, Noto Sans Kannada, Noto Sans Khmer, Noto Sans Lao, Noto Sans Malayalam, Noto Sans Mongolian, Noto Sans Myanmar, Noto Sans Oriya, Noto Sans Sinhala, Noto Sans Tamil, Noto Sans Telugu, Noto Sans Thaana, Noto Sans Thai, Noto Sans Tibetan, Noto Sans Yi, Noto Serif Armenian, Noto Serif Khmer, Noto Serif Lao, Noto Serif Thai");
+pref("font.name-list.monospace.x-beng", "Noto Sans Bengali, Cousine, Courier, Courier New, Noto Naskh Arabic, Noto Sans Armenian, Noto Sans Bengali, Noto Sans Buginese, Noto Sans JP Regular, Noto Sans KR Regular, Noto Sans SC Regular, Noto Sans TC Regular, Noto Sans Canadian Aboriginal, Noto Sans Cherokee, Noto Sans Devanagari, Noto Sans Ethiopic, Noto Sans Georgian, Noto Sans Gujarati, Noto Sans Gurmukhi, Noto Sans Hebrew, Noto Sans Kannada, Noto Sans Khmer, Noto Sans Lao, Noto Sans Malayalam, Noto Sans Mongolian, Noto Sans Myanmar, Noto Sans Oriya, Noto Sans Sinhala, Noto Sans Tamil, Noto Sans Telugu, Noto Sans Thaana, Noto Sans Thai, Noto Sans Tibetan, Noto Sans Yi, Noto Serif Armenian, Noto Serif Khmer, Noto Serif Lao, Noto Serif Thai");
+pref("font.name-list.monospace.x-cyrillic", "Cousine, Courier, Courier New, Noto Naskh Arabic, Noto Sans Armenian, Noto Sans Bengali, Noto Sans Buginese, Noto Sans JP Regular, Noto Sans KR Regular, Noto Sans SC Regular, Noto Sans TC Regular, Noto Sans Canadian Aboriginal, Noto Sans Cherokee, Noto Sans Devanagari, Noto Sans Ethiopic, Noto Sans Georgian, Noto Sans Gujarati, Noto Sans Gurmukhi, Noto Sans Hebrew, Noto Sans Kannada, Noto Sans Khmer, Noto Sans Lao, Noto Sans Malayalam, Noto Sans Mongolian, Noto Sans Myanmar, Noto Sans Oriya, Noto Sans Sinhala, Noto Sans Tamil, Noto Sans Telugu, Noto Sans Thaana, Noto Sans Thai, Noto Sans Tibetan, Noto Sans Yi, Noto Serif Armenian, Noto Serif Khmer, Noto Serif Lao, Noto Serif Thai");
+pref("font.name-list.monospace.x-devanagari", "Noto Sans Devanagari, Cousine, Courier, Courier New, Noto Naskh Arabic, Noto Sans Armenian, Noto Sans Bengali, Noto Sans Buginese, Noto Sans JP Regular, Noto Sans KR Regular, Noto Sans SC Regular, Noto Sans TC Regular, Noto Sans Canadian Aboriginal, Noto Sans Cherokee, Noto Sans Devanagari, Noto Sans Ethiopic, Noto Sans Georgian, Noto Sans Gujarati, Noto Sans Gurmukhi, Noto Sans Hebrew, Noto Sans Kannada, Noto Sans Khmer, Noto Sans Lao, Noto Sans Malayalam, Noto Sans Mongolian, Noto Sans Myanmar, Noto Sans Oriya, Noto Sans Sinhala, Noto Sans Tamil, Noto Sans Telugu, Noto Sans Thaana, Noto Sans Thai, Noto Sans Tibetan, Noto Sans Yi, Noto Serif Armenian, Noto Serif Khmer, Noto Serif Lao, Noto Serif Thai");
+pref("font.name-list.monospace.x-ethi", "Noto Sans Ethiopic, Cousine, Courier, Courier New, Noto Naskh Arabic, Noto Sans Armenian, Noto Sans Bengali, Noto Sans Buginese, Noto Sans JP Regular, Noto Sans KR Regular, Noto Sans SC Regular, Noto Sans TC Regular, Noto Sans Canadian Aboriginal, Noto Sans Cherokee, Noto Sans Devanagari, Noto Sans Ethiopic, Noto Sans Georgian, Noto Sans Gujarati, Noto Sans Gurmukhi, Noto Sans Hebrew, Noto Sans Kannada, Noto Sans Khmer, Noto Sans Lao, Noto Sans Malayalam, Noto Sans Mongolian, Noto Sans Myanmar, Noto Sans Oriya, Noto Sans Sinhala, Noto Sans Tamil, Noto Sans Telugu, Noto Sans Thaana, Noto Sans Thai, Noto Sans Tibetan, Noto Sans Yi, Noto Serif Armenian, Noto Serif Khmer, Noto Serif Lao, Noto Serif Thai");
+pref("font.name-list.monospace.x-geor", "Noto Sans Georgian, Cousine, Courier, Courier New, Noto Naskh Arabic, Noto Sans Armenian, Noto Sans Bengali, Noto Sans Buginese, Noto Sans JP Regular, Noto Sans KR Regular, Noto Sans SC Regular, Noto Sans TC Regular, Noto Sans Canadian Aboriginal, Noto Sans Cherokee, Noto Sans Devanagari, Noto Sans Ethiopic, Noto Sans Georgian, Noto Sans Gujarati, Noto Sans Gurmukhi, Noto Sans Hebrew, Noto Sans Kannada, Noto Sans Khmer, Noto Sans Lao, Noto Sans Malayalam, Noto Sans Mongolian, Noto Sans Myanmar, Noto Sans Oriya, Noto Sans Sinhala, Noto Sans Tamil, Noto Sans Telugu, Noto Sans Thaana, Noto Sans Thai, Noto Sans Tibetan, Noto Sans Yi, Noto Serif Armenian, Noto Serif Khmer, Noto Serif Lao, Noto Serif Thai");
+pref("font.name-list.monospace.x-gujr", "Noto Sans Gujarati, Cousine, Courier, Courier New, Noto Naskh Arabic, Noto Sans Armenian, Noto Sans Bengali, Noto Sans Buginese, Noto Sans JP Regular, Noto Sans KR Regular, Noto Sans SC Regular, Noto Sans TC Regular, Noto Sans Canadian Aboriginal, Noto Sans Cherokee, Noto Sans Devanagari, Noto Sans Ethiopic, Noto Sans Georgian, Noto Sans Gujarati, Noto Sans Gurmukhi, Noto Sans Hebrew, Noto Sans Kannada, Noto Sans Khmer, Noto Sans Lao, Noto Sans Malayalam, Noto Sans Mongolian, Noto Sans Myanmar, Noto Sans Oriya, Noto Sans Sinhala, Noto Sans Tamil, Noto Sans Telugu, Noto Sans Thaana, Noto Sans Thai, Noto Sans Tibetan, Noto Sans Yi, Noto Serif Armenian, Noto Serif Khmer, Noto Serif Lao, Noto Serif Thai");
+pref("font.name-list.monospace.x-guru", "Noto Sans Gurmukhi, Cousine, Courier, Courier New, Noto Naskh Arabic, Noto Sans Armenian, Noto Sans Bengali, Noto Sans Buginese, Noto Sans JP Regular, Noto Sans KR Regular, Noto Sans SC Regular, Noto Sans TC Regular, Noto Sans Canadian Aboriginal, Noto Sans Cherokee, Noto Sans Devanagari, Noto Sans Ethiopic, Noto Sans Georgian, Noto Sans Gujarati, Noto Sans Gurmukhi, Noto Sans Hebrew, Noto Sans Kannada, Noto Sans Khmer, Noto Sans Lao, Noto Sans Malayalam, Noto Sans Mongolian, Noto Sans Myanmar, Noto Sans Oriya, Noto Sans Sinhala, Noto Sans Tamil, Noto Sans Telugu, Noto Sans Thaana, Noto Sans Thai, Noto Sans Tibetan, Noto Sans Yi, Noto Serif Armenian, Noto Serif Khmer, Noto Serif Lao, Noto Serif Thai");
+pref("font.name-list.monospace.x-khmr", "Noto Sans Khmer, Cousine, Courier, Courier New, Noto Naskh Arabic, Noto Sans Armenian, Noto Sans Bengali, Noto Sans Buginese, Noto Sans JP Regular, Noto Sans KR Regular, Noto Sans SC Regular, Noto Sans TC Regular, Noto Sans Canadian Aboriginal, Noto Sans Cherokee, Noto Sans Devanagari, Noto Sans Ethiopic, Noto Sans Georgian, Noto Sans Gujarati, Noto Sans Gurmukhi, Noto Sans Hebrew, Noto Sans Kannada, Noto Sans Khmer, Noto Sans Lao, Noto Sans Malayalam, Noto Sans Mongolian, Noto Sans Myanmar, Noto Sans Oriya, Noto Sans Sinhala, Noto Sans Tamil, Noto Sans Telugu, Noto Sans Thaana, Noto Sans Thai, Noto Sans Tibetan, Noto Sans Yi, Noto Serif Armenian, Noto Serif Khmer, Noto Serif Lao, Noto Serif Thai");
+pref("font.name-list.monospace.x-knda", "Noto Sans Kannada, Cousine, Courier, Courier New, Noto Naskh Arabic, Noto Sans Armenian, Noto Sans Bengali, Noto Sans Buginese, Noto Sans JP Regular, Noto Sans KR Regular, Noto Sans SC Regular, Noto Sans TC Regular, Noto Sans Canadian Aboriginal, Noto Sans Cherokee, Noto Sans Devanagari, Noto Sans Ethiopic, Noto Sans Georgian, Noto Sans Gujarati, Noto Sans Gurmukhi, Noto Sans Hebrew, Noto Sans Kannada, Noto Sans Khmer, Noto Sans Lao, Noto Sans Malayalam, Noto Sans Mongolian, Noto Sans Myanmar, Noto Sans Oriya, Noto Sans Sinhala, Noto Sans Tamil, Noto Sans Telugu, Noto Sans Thaana, Noto Sans Thai, Noto Sans Tibetan, Noto Sans Yi, Noto Serif Armenian, Noto Serif Khmer, Noto Serif Lao, Noto Serif Thai");
+pref("font.name-list.monospace.x-mlym", "Noto Sans Malayalam, Cousine, Courier, Courier New, Noto Naskh Arabic, Noto Sans Armenian, Noto Sans Bengali, Noto Sans Buginese, Noto Sans JP Regular, Noto Sans KR Regular, Noto Sans SC Regular, Noto Sans TC Regular, Noto Sans Canadian Aboriginal, Noto Sans Cherokee, Noto Sans Devanagari, Noto Sans Ethiopic, Noto Sans Georgian, Noto Sans Gujarati, Noto Sans Gurmukhi, Noto Sans Hebrew, Noto Sans Kannada, Noto Sans Khmer, Noto Sans Lao, Noto Sans Malayalam, Noto Sans Mongolian, Noto Sans Myanmar, Noto Sans Oriya, Noto Sans Sinhala, Noto Sans Tamil, Noto Sans Telugu, Noto Sans Thaana, Noto Sans Thai, Noto Sans Tibetan, Noto Sans Yi, Noto Serif Armenian, Noto Serif Khmer, Noto Serif Lao, Noto Serif Thai");
+pref("font.name-list.monospace.x-orya", "Noto Sans Oriya, Cousine, Courier, Courier New, Noto Naskh Arabic, Noto Sans Armenian, Noto Sans Bengali, Noto Sans Buginese, Noto Sans JP Regular, Noto Sans KR Regular, Noto Sans SC Regular, Noto Sans TC Regular, Noto Sans Canadian Aboriginal, Noto Sans Cherokee, Noto Sans Devanagari, Noto Sans Ethiopic, Noto Sans Georgian, Noto Sans Gujarati, Noto Sans Gurmukhi, Noto Sans Hebrew, Noto Sans Kannada, Noto Sans Khmer, Noto Sans Lao, Noto Sans Malayalam, Noto Sans Mongolian, Noto Sans Myanmar, Noto Sans Oriya, Noto Sans Sinhala, Noto Sans Tamil, Noto Sans Telugu, Noto Sans Thaana, Noto Sans Thai, Noto Sans Tibetan, Noto Sans Yi, Noto Serif Armenian, Noto Serif Khmer, Noto Serif Lao, Noto Serif Thai");
+pref("font.name-list.monospace.x-sinh", "Noto Sans Sinhala, Cousine, Courier, Courier New, Noto Naskh Arabic, Noto Sans Armenian, Noto Sans Bengali, Noto Sans Buginese, Noto Sans JP Regular, Noto Sans KR Regular, Noto Sans SC Regular, Noto Sans TC Regular, Noto Sans Canadian Aboriginal, Noto Sans Cherokee, Noto Sans Devanagari, Noto Sans Ethiopic, Noto Sans Georgian, Noto Sans Gujarati, Noto Sans Gurmukhi, Noto Sans Hebrew, Noto Sans Kannada, Noto Sans Khmer, Noto Sans Lao, Noto Sans Malayalam, Noto Sans Mongolian, Noto Sans Myanmar, Noto Sans Oriya, Noto Sans Sinhala, Noto Sans Tamil, Noto Sans Telugu, Noto Sans Thaana, Noto Sans Thai, Noto Sans Tibetan, Noto Sans Yi, Noto Serif Armenian, Noto Serif Khmer, Noto Serif Lao, Noto Serif Thai");
+pref("font.name-list.monospace.x-tamil", "Noto Sans Tamil, Cousine, Courier, Courier New, Noto Naskh Arabic, Noto Sans Armenian, Noto Sans Bengali, Noto Sans Buginese, Noto Sans JP Regular, Noto Sans KR Regular, Noto Sans SC Regular, Noto Sans TC Regular, Noto Sans Canadian Aboriginal, Noto Sans Cherokee, Noto Sans Devanagari, Noto Sans Ethiopic, Noto Sans Georgian, Noto Sans Gujarati, Noto Sans Gurmukhi, Noto Sans Hebrew, Noto Sans Kannada, Noto Sans Khmer, Noto Sans Lao, Noto Sans Malayalam, Noto Sans Mongolian, Noto Sans Myanmar, Noto Sans Oriya, Noto Sans Sinhala, Noto Sans Tamil, Noto Sans Telugu, Noto Sans Thaana, Noto Sans Thai, Noto Sans Tibetan, Noto Sans Yi, Noto Serif Armenian, Noto Serif Khmer, Noto Serif Lao, Noto Serif Thai");
+pref("font.name-list.monospace.x-telu", "Noto Sans Telugu, Cousine, Courier, Courier New, Noto Naskh Arabic, Noto Sans Armenian, Noto Sans Bengali, Noto Sans Buginese, Noto Sans JP Regular, Noto Sans KR Regular, Noto Sans SC Regular, Noto Sans TC Regular, Noto Sans Canadian Aboriginal, Noto Sans Cherokee, Noto Sans Devanagari, Noto Sans Ethiopic, Noto Sans Georgian, Noto Sans Gujarati, Noto Sans Gurmukhi, Noto Sans Hebrew, Noto Sans Kannada, Noto Sans Khmer, Noto Sans Lao, Noto Sans Malayalam, Noto Sans Mongolian, Noto Sans Myanmar, Noto Sans Oriya, Noto Sans Sinhala, Noto Sans Tamil, Noto Sans Telugu, Noto Sans Thaana, Noto Sans Thai, Noto Sans Tibetan, Noto Sans Yi, Noto Serif Armenian, Noto Serif Khmer, Noto Serif Lao, Noto Serif Thai");
+pref("font.name-list.monospace.x-tibt", "Noto Sans Tibetan, Cousine, Courier, Courier New, Noto Naskh Arabic, Noto Sans Armenian, Noto Sans Bengali, Noto Sans Buginese, Noto Sans JP Regular, Noto Sans KR Regular, Noto Sans SC Regular, Noto Sans TC Regular, Noto Sans Canadian Aboriginal, Noto Sans Cherokee, Noto Sans Devanagari, Noto Sans Ethiopic, Noto Sans Georgian, Noto Sans Gujarati, Noto Sans Gurmukhi, Noto Sans Hebrew, Noto Sans Kannada, Noto Sans Khmer, Noto Sans Lao, Noto Sans Malayalam, Noto Sans Mongolian, Noto Sans Myanmar, Noto Sans Oriya, Noto Sans Sinhala, Noto Sans Tamil, Noto Sans Telugu, Noto Sans Thaana, Noto Sans Thai, Noto Sans Tibetan, Noto Sans Yi, Noto Serif Armenian, Noto Serif Khmer, Noto Serif Lao, Noto Serif Thai");
+pref("font.name-list.monospace.x-unicode", "Cousine, Courier, Courier New, Noto Naskh Arabic, Noto Sans Armenian, Noto Sans Bengali, Noto Sans Buginese, Noto Sans JP Regular, Noto Sans KR Regular, Noto Sans SC Regular, Noto Sans TC Regular, Noto Sans Canadian Aboriginal, Noto Sans Cherokee, Noto Sans Devanagari, Noto Sans Ethiopic, Noto Sans Georgian, Noto Sans Gujarati, Noto Sans Gurmukhi, Noto Sans Hebrew, Noto Sans Kannada, Noto Sans Khmer, Noto Sans Lao, Noto Sans Malayalam, Noto Sans Mongolian, Noto Sans Myanmar, Noto Sans Oriya, Noto Sans Sinhala, Noto Sans Tamil, Noto Sans Telugu, Noto Sans Thaana, Noto Sans Thai, Noto Sans Tibetan, Noto Sans Yi, Noto Serif Armenian, Noto Serif Khmer, Noto Serif Lao, Noto Serif Thai");
+pref("font.name-list.monospace.x-western", "Cousine, Courier, Courier New, Noto Naskh Arabic, Noto Sans Armenian, Noto Sans Bengali, Noto Sans Buginese, Noto Sans JP Regular, Noto Sans KR Regular, Noto Sans SC Regular, Noto Sans TC Regular, Noto Sans Canadian Aboriginal, Noto Sans Cherokee, Noto Sans Devanagari, Noto Sans Ethiopic, Noto Sans Georgian, Noto Sans Gujarati, Noto Sans Gurmukhi, Noto Sans Hebrew, Noto Sans Kannada, Noto Sans Khmer, Noto Sans Lao, Noto Sans Malayalam, Noto Sans Mongolian, Noto Sans Myanmar, Noto Sans Oriya, Noto Sans Sinhala, Noto Sans Tamil, Noto Sans Telugu, Noto Sans Thaana, Noto Sans Thai, Noto Sans Tibetan, Noto Sans Yi, Noto Serif Armenian, Noto Serif Khmer, Noto Serif Lao, Noto Serif Thai");
+pref("font.name-list.monospace.zh-CN", "Noto Sans SC Regular, Cousine, Courier, Courier New, Noto Naskh Arabic, Noto Sans Armenian, Noto Sans Bengali, Noto Sans Buginese, Noto Sans JP Regular, Noto Sans KR Regular, Noto Sans SC Regular, Noto Sans TC Regular, Noto Sans Canadian Aboriginal, Noto Sans Cherokee, Noto Sans Devanagari, Noto Sans Ethiopic, Noto Sans Georgian, Noto Sans Gujarati, Noto Sans Gurmukhi, Noto Sans Hebrew, Noto Sans Kannada, Noto Sans Khmer, Noto Sans Lao, Noto Sans Malayalam, Noto Sans Mongolian, Noto Sans Myanmar, Noto Sans Oriya, Noto Sans Sinhala, Noto Sans Tamil, Noto Sans Telugu, Noto Sans Thaana, Noto Sans Thai, Noto Sans Tibetan, Noto Sans Yi, Noto Serif Armenian, Noto Serif Khmer, Noto Serif Lao, Noto Serif Thai");
+pref("font.name-list.monospace.zh-HK", "Noto Sans TC Regular, Cousine, Courier, Courier New, Noto Naskh Arabic, Noto Sans Armenian, Noto Sans Bengali, Noto Sans Buginese, Noto Sans JP Regular, Noto Sans KR Regular, Noto Sans SC Regular, Noto Sans TC Regular, Noto Sans Canadian Aboriginal, Noto Sans Cherokee, Noto Sans Devanagari, Noto Sans Ethiopic, Noto Sans Georgian, Noto Sans Gujarati, Noto Sans Gurmukhi, Noto Sans Hebrew, Noto Sans Kannada, Noto Sans Khmer, Noto Sans Lao, Noto Sans Malayalam, Noto Sans Mongolian, Noto Sans Myanmar, Noto Sans Oriya, Noto Sans Sinhala, Noto Sans Tamil, Noto Sans Telugu, Noto Sans Thaana, Noto Sans Thai, Noto Sans Tibetan, Noto Sans Yi, Noto Serif Armenian, Noto Serif Khmer, Noto Serif Lao, Noto Serif Thai");
+pref("font.name-list.monospace.zh-TW", "Noto Sans TC Regular, Cousine, Courier, Courier New, Noto Naskh Arabic, Noto Sans Armenian, Noto Sans Bengali, Noto Sans Buginese, Noto Sans JP Regular, Noto Sans KR Regular, Noto Sans SC Regular, Noto Sans TC Regular, Noto Sans Canadian Aboriginal, Noto Sans Cherokee, Noto Sans Devanagari, Noto Sans Ethiopic, Noto Sans Georgian, Noto Sans Gujarati, Noto Sans Gurmukhi, Noto Sans Hebrew, Noto Sans Kannada, Noto Sans Khmer, Noto Sans Lao, Noto Sans Malayalam, Noto Sans Mongolian, Noto Sans Myanmar, Noto Sans Oriya, Noto Sans Sinhala, Noto Sans Tamil, Noto Sans Telugu, Noto Sans Thaana, Noto Sans Thai, Noto Sans Tibetan, Noto Sans Yi, Noto Serif Armenian, Noto Serif Khmer, Noto Serif Lao, Noto Serif Thai");
+pref("font.name-list.sans-serif.ar", "Noto Naskh Arabic, Arimo, Arial, Verdana, Noto Naskh Arabic, Noto Sans Armenian, Noto Sans Bengali, Noto Sans Buginese, Noto Sans JP Regular, Noto Sans KR Regular, Noto Sans SC Regular, Noto Sans TC Regular, Noto Sans Canadian Aboriginal, Noto Sans Cherokee, Noto Sans Devanagari, Noto Sans Ethiopic, Noto Sans Georgian, Noto Sans Gujarati, Noto Sans Gurmukhi, Noto Sans Hebrew, Noto Sans Kannada, Noto Sans Khmer, Noto Sans Lao, Noto Sans Malayalam, Noto Sans Mongolian, Noto Sans Myanmar, Noto Sans Oriya, Noto Sans Sinhala, Noto Sans Tamil, Noto Sans Telugu, Noto Sans Thaana, Noto Sans Thai, Noto Sans Tibetan, Noto Sans Yi, Noto Serif Armenian, Noto Serif Khmer, Noto Serif Lao, Noto Serif Thai");
+pref("font.name-list.sans-serif.el", "Arimo, Arial, Verdana, Noto Naskh Arabic, Noto Sans Armenian, Noto Sans Bengali, Noto Sans Buginese, Noto Sans JP Regular, Noto Sans KR Regular, Noto Sans SC Regular, Noto Sans TC Regular, Noto Sans Canadian Aboriginal, Noto Sans Cherokee, Noto Sans Devanagari, Noto Sans Ethiopic, Noto Sans Georgian, Noto Sans Gujarati, Noto Sans Gurmukhi, Noto Sans Hebrew, Noto Sans Kannada, Noto Sans Khmer, Noto Sans Lao, Noto Sans Malayalam, Noto Sans Mongolian, Noto Sans Myanmar, Noto Sans Oriya, Noto Sans Sinhala, Noto Sans Tamil, Noto Sans Telugu, Noto Sans Thaana, Noto Sans Thai, Noto Sans Tibetan, Noto Sans Yi, Noto Serif Armenian, Noto Serif Khmer, Noto Serif Lao, Noto Serif Thai");
+pref("font.name-list.sans-serif.he", "Noto Sans Hebrew, Arimo, Arial, Verdana, Noto Naskh Arabic, Noto Sans Armenian, Noto Sans Bengali, Noto Sans Buginese, Noto Sans JP Regular, Noto Sans KR Regular, Noto Sans SC Regular, Noto Sans TC Regular, Noto Sans Canadian Aboriginal, Noto Sans Cherokee, Noto Sans Devanagari, Noto Sans Ethiopic, Noto Sans Georgian, Noto Sans Gujarati, Noto Sans Gurmukhi, Noto Sans Hebrew, Noto Sans Kannada, Noto Sans Khmer, Noto Sans Lao, Noto Sans Malayalam, Noto Sans Mongolian, Noto Sans Myanmar, Noto Sans Oriya, Noto Sans Sinhala, Noto Sans Tamil, Noto Sans Telugu, Noto Sans Thaana, Noto Sans Thai, Noto Sans Tibetan, Noto Sans Yi, Noto Serif Armenian, Noto Serif Khmer, Noto Serif Lao, Noto Serif Thai");
+pref("font.name-list.sans-serif.ja", "Noto Sans JP Regular, Arimo, Arial, Verdana, Noto Naskh Arabic, Noto Sans Armenian, Noto Sans Bengali, Noto Sans Buginese, Noto Sans JP Regular, Noto Sans KR Regular, Noto Sans SC Regular, Noto Sans TC Regular, Noto Sans Canadian Aboriginal, Noto Sans Cherokee, Noto Sans Devanagari, Noto Sans Ethiopic, Noto Sans Georgian, Noto Sans Gujarati, Noto Sans Gurmukhi, Noto Sans Hebrew, Noto Sans Kannada, Noto Sans Khmer, Noto Sans Lao, Noto Sans Malayalam, Noto Sans Mongolian, Noto Sans Myanmar, Noto Sans Oriya, Noto Sans Sinhala, Noto Sans Tamil, Noto Sans Telugu, Noto Sans Thaana, Noto Sans Thai, Noto Sans Tibetan, Noto Sans Yi, Noto Serif Armenian, Noto Serif Khmer, Noto Serif Lao, Noto Serif Thai");
+pref("font.name-list.sans-serif.ko", "Noto Sans KR Regular, Arimo, Arial, Verdana, Noto Naskh Arabic, Noto Sans Armenian, Noto Sans Bengali, Noto Sans Buginese, Noto Sans JP Regular, Noto Sans KR Regular, Noto Sans SC Regular, Noto Sans TC Regular, Noto Sans Canadian Aboriginal, Noto Sans Cherokee, Noto Sans Devanagari, Noto Sans Ethiopic, Noto Sans Georgian, Noto Sans Gujarati, Noto Sans Gurmukhi, Noto Sans Hebrew, Noto Sans Kannada, Noto Sans Khmer, Noto Sans Lao, Noto Sans Malayalam, Noto Sans Mongolian, Noto Sans Myanmar, Noto Sans Oriya, Noto Sans Sinhala, Noto Sans Tamil, Noto Sans Telugu, Noto Sans Thaana, Noto Sans Thai, Noto Sans Tibetan, Noto Sans Yi, Noto Serif Armenian, Noto Serif Khmer, Noto Serif Lao, Noto Serif Thai");
+pref("font.name-list.sans-serif.th", "Noto Sans Thai, Arimo, Arial, Verdana, Noto Naskh Arabic, Noto Sans Armenian, Noto Sans Bengali, Noto Sans Buginese, Noto Sans JP Regular, Noto Sans KR Regular, Noto Sans SC Regular, Noto Sans TC Regular, Noto Sans Canadian Aboriginal, Noto Sans Cherokee, Noto Sans Devanagari, Noto Sans Ethiopic, Noto Sans Georgian, Noto Sans Gujarati, Noto Sans Gurmukhi, Noto Sans Hebrew, Noto Sans Kannada, Noto Sans Khmer, Noto Sans Lao, Noto Sans Malayalam, Noto Sans Mongolian, Noto Sans Myanmar, Noto Sans Oriya, Noto Sans Sinhala, Noto Sans Tamil, Noto Sans Telugu, Noto Sans Thaana, Noto Sans Thai, Noto Sans Tibetan, Noto Sans Yi, Noto Serif Armenian, Noto Serif Khmer, Noto Serif Lao, Noto Serif Thai");
+pref("font.name-list.sans-serif.x-armn", "Noto Sans Armenian, Arimo, Arial, Verdana, Noto Naskh Arabic, Noto Sans Armenian, Noto Sans Bengali, Noto Sans Buginese, Noto Sans JP Regular, Noto Sans KR Regular, Noto Sans SC Regular, Noto Sans TC Regular, Noto Sans Canadian Aboriginal, Noto Sans Cherokee, Noto Sans Devanagari, Noto Sans Ethiopic, Noto Sans Georgian, Noto Sans Gujarati, Noto Sans Gurmukhi, Noto Sans Hebrew, Noto Sans Kannada, Noto Sans Khmer, Noto Sans Lao, Noto Sans Malayalam, Noto Sans Mongolian, Noto Sans Myanmar, Noto Sans Oriya, Noto Sans Sinhala, Noto Sans Tamil, Noto Sans Telugu, Noto Sans Thaana, Noto Sans Thai, Noto Sans Tibetan, Noto Sans Yi, Noto Serif Armenian, Noto Serif Khmer, Noto Serif Lao, Noto Serif Thai");
+pref("font.name-list.sans-serif.x-beng", "Noto Sans Bengali, Arimo, Arial, Verdana, Noto Naskh Arabic, Noto Sans Armenian, Noto Sans Bengali, Noto Sans Buginese, Noto Sans JP Regular, Noto Sans KR Regular, Noto Sans SC Regular, Noto Sans TC Regular, Noto Sans Canadian Aboriginal, Noto Sans Cherokee, Noto Sans Devanagari, Noto Sans Ethiopic, Noto Sans Georgian, Noto Sans Gujarati, Noto Sans Gurmukhi, Noto Sans Hebrew, Noto Sans Kannada, Noto Sans Khmer, Noto Sans Lao, Noto Sans Malayalam, Noto Sans Mongolian, Noto Sans Myanmar, Noto Sans Oriya, Noto Sans Sinhala, Noto Sans Tamil, Noto Sans Telugu, Noto Sans Thaana, Noto Sans Thai, Noto Sans Tibetan, Noto Sans Yi, Noto Serif Armenian, Noto Serif Khmer, Noto Serif Lao, Noto Serif Thai");
+pref("font.name-list.sans-serif.x-cyrillic", "Arimo, Arial, Verdana, Noto Naskh Arabic, Noto Sans Armenian, Noto Sans Bengali, Noto Sans Buginese, Noto Sans JP Regular, Noto Sans KR Regular, Noto Sans SC Regular, Noto Sans TC Regular, Noto Sans Canadian Aboriginal, Noto Sans Cherokee, Noto Sans Devanagari, Noto Sans Ethiopic, Noto Sans Georgian, Noto Sans Gujarati, Noto Sans Gurmukhi, Noto Sans Hebrew, Noto Sans Kannada, Noto Sans Khmer, Noto Sans Lao, Noto Sans Malayalam, Noto Sans Mongolian, Noto Sans Myanmar, Noto Sans Oriya, Noto Sans Sinhala, Noto Sans Tamil, Noto Sans Telugu, Noto Sans Thaana, Noto Sans Thai, Noto Sans Tibetan, Noto Sans Yi, Noto Serif Armenian, Noto Serif Khmer, Noto Serif Lao, Noto Serif Thai");
+pref("font.name-list.sans-serif.x-devanagari", "Noto Sans Devanagari, Arimo, Arial, Verdana, Noto Naskh Arabic, Noto Sans Armenian, Noto Sans Bengali, Noto Sans Buginese, Noto Sans JP Regular, Noto Sans KR Regular, Noto Sans SC Regular, Noto Sans TC Regular, Noto Sans Canadian Aboriginal, Noto Sans Cherokee, Noto Sans Devanagari, Noto Sans Ethiopic, Noto Sans Georgian, Noto Sans Gujarati, Noto Sans Gurmukhi, Noto Sans Hebrew, Noto Sans Kannada, Noto Sans Khmer, Noto Sans Lao, Noto Sans Malayalam, Noto Sans Mongolian, Noto Sans Myanmar, Noto Sans Oriya, Noto Sans Sinhala, Noto Sans Tamil, Noto Sans Telugu, Noto Sans Thaana, Noto Sans Thai, Noto Sans Tibetan, Noto Sans Yi, Noto Serif Armenian, Noto Serif Khmer, Noto Serif Lao, Noto Serif Thai");
+pref("font.name-list.sans-serif.x-ethi", "Noto Sans Ethiopic, Arimo, Arial, Verdana, Noto Naskh Arabic, Noto Sans Armenian, Noto Sans Bengali, Noto Sans Buginese, Noto Sans JP Regular, Noto Sans KR Regular, Noto Sans SC Regular, Noto Sans TC Regular, Noto Sans Canadian Aboriginal, Noto Sans Cherokee, Noto Sans Devanagari, Noto Sans Ethiopic, Noto Sans Georgian, Noto Sans Gujarati, Noto Sans Gurmukhi, Noto Sans Hebrew, Noto Sans Kannada, Noto Sans Khmer, Noto Sans Lao, Noto Sans Malayalam, Noto Sans Mongolian, Noto Sans Myanmar, Noto Sans Oriya, Noto Sans Sinhala, Noto Sans Tamil, Noto Sans Telugu, Noto Sans Thaana, Noto Sans Thai, Noto Sans Tibetan, Noto Sans Yi, Noto Serif Armenian, Noto Serif Khmer, Noto Serif Lao, Noto Serif Thai");
+pref("font.name-list.sans-serif.x-geor", "Noto Sans Georgian, Arimo, Arial, Verdana, Noto Naskh Arabic, Noto Sans Armenian, Noto Sans Bengali, Noto Sans Buginese, Noto Sans JP Regular, Noto Sans KR Regular, Noto Sans SC Regular, Noto Sans TC Regular, Noto Sans Canadian Aboriginal, Noto Sans Cherokee, Noto Sans Devanagari, Noto Sans Ethiopic, Noto Sans Georgian, Noto Sans Gujarati, Noto Sans Gurmukhi, Noto Sans Hebrew, Noto Sans Kannada, Noto Sans Khmer, Noto Sans Lao, Noto Sans Malayalam, Noto Sans Mongolian, Noto Sans Myanmar, Noto Sans Oriya, Noto Sans Sinhala, Noto Sans Tamil, Noto Sans Telugu, Noto Sans Thaana, Noto Sans Thai, Noto Sans Tibetan, Noto Sans Yi, Noto Serif Armenian, Noto Serif Khmer, Noto Serif Lao, Noto Serif Thai");
+pref("font.name-list.sans-serif.x-gujr", "Noto Sans Gujarati, Arimo, Arial, Verdana, Noto Naskh Arabic, Noto Sans Armenian, Noto Sans Bengali, Noto Sans Buginese, Noto Sans JP Regular, Noto Sans KR Regular, Noto Sans SC Regular, Noto Sans TC Regular, Noto Sans Canadian Aboriginal, Noto Sans Cherokee, Noto Sans Devanagari, Noto Sans Ethiopic, Noto Sans Georgian, Noto Sans Gujarati, Noto Sans Gurmukhi, Noto Sans Hebrew, Noto Sans Kannada, Noto Sans Khmer, Noto Sans Lao, Noto Sans Malayalam, Noto Sans Mongolian, Noto Sans Myanmar, Noto Sans Oriya, Noto Sans Sinhala, Noto Sans Tamil, Noto Sans Telugu, Noto Sans Thaana, Noto Sans Thai, Noto Sans Tibetan, Noto Sans Yi, Noto Serif Armenian, Noto Serif Khmer, Noto Serif Lao, Noto Serif Thai");
+pref("font.name-list.sans-serif.x-guru", "Noto Sans Gurmukhi, Arimo, Arial, Verdana, Noto Naskh Arabic, Noto Sans Armenian, Noto Sans Bengali, Noto Sans Buginese, Noto Sans JP Regular, Noto Sans KR Regular, Noto Sans SC Regular, Noto Sans TC Regular, Noto Sans Canadian Aboriginal, Noto Sans Cherokee, Noto Sans Devanagari, Noto Sans Ethiopic, Noto Sans Georgian, Noto Sans Gujarati, Noto Sans Gurmukhi, Noto Sans Hebrew, Noto Sans Kannada, Noto Sans Khmer, Noto Sans Lao, Noto Sans Malayalam, Noto Sans Mongolian, Noto Sans Myanmar, Noto Sans Oriya, Noto Sans Sinhala, Noto Sans Tamil, Noto Sans Telugu, Noto Sans Thaana, Noto Sans Thai, Noto Sans Tibetan, Noto Sans Yi, Noto Serif Armenian, Noto Serif Khmer, Noto Serif Lao, Noto Serif Thai");
+pref("font.name-list.sans-serif.x-khmr", "Noto Sans Khmer, Arimo, Arial, Verdana, Noto Naskh Arabic, Noto Sans Armenian, Noto Sans Bengali, Noto Sans Buginese, Noto Sans JP Regular, Noto Sans KR Regular, Noto Sans SC Regular, Noto Sans TC Regular, Noto Sans Canadian Aboriginal, Noto Sans Cherokee, Noto Sans Devanagari, Noto Sans Ethiopic, Noto Sans Georgian, Noto Sans Gujarati, Noto Sans Gurmukhi, Noto Sans Hebrew, Noto Sans Kannada, Noto Sans Khmer, Noto Sans Lao, Noto Sans Malayalam, Noto Sans Mongolian, Noto Sans Myanmar, Noto Sans Oriya, Noto Sans Sinhala, Noto Sans Tamil, Noto Sans Telugu, Noto Sans Thaana, Noto Sans Thai, Noto Sans Tibetan, Noto Sans Yi, Noto Serif Armenian, Noto Serif Khmer, Noto Serif Lao, Noto Serif Thai");
+pref("font.name-list.sans-serif.x-knda", "Noto Sans Kannada, Arimo, Arial, Verdana, Noto Naskh Arabic, Noto Sans Armenian, Noto Sans Bengali, Noto Sans Buginese, Noto Sans JP Regular, Noto Sans KR Regular, Noto Sans SC Regular, Noto Sans TC Regular, Noto Sans Canadian Aboriginal, Noto Sans Cherokee, Noto Sans Devanagari, Noto Sans Ethiopic, Noto Sans Georgian, Noto Sans Gujarati, Noto Sans Gurmukhi, Noto Sans Hebrew, Noto Sans Kannada, Noto Sans Khmer, Noto Sans Lao, Noto Sans Malayalam, Noto Sans Mongolian, Noto Sans Myanmar, Noto Sans Oriya, Noto Sans Sinhala, Noto Sans Tamil, Noto Sans Telugu, Noto Sans Thaana, Noto Sans Thai, Noto Sans Tibetan, Noto Sans Yi, Noto Serif Armenian, Noto Serif Khmer, Noto Serif Lao, Noto Serif Thai");
+pref("font.name-list.sans-serif.x-mlym", "Noto Sans Malayalam, Arimo, Arial, Verdana, Noto Naskh Arabic, Noto Sans Armenian, Noto Sans Bengali, Noto Sans Buginese, Noto Sans JP Regular, Noto Sans KR Regular, Noto Sans SC Regular, Noto Sans TC Regular, Noto Sans Canadian Aboriginal, Noto Sans Cherokee, Noto Sans Devanagari, Noto Sans Ethiopic, Noto Sans Georgian, Noto Sans Gujarati, Noto Sans Gurmukhi, Noto Sans Hebrew, Noto Sans Kannada, Noto Sans Khmer, Noto Sans Lao, Noto Sans Malayalam, Noto Sans Mongolian, Noto Sans Myanmar, Noto Sans Oriya, Noto Sans Sinhala, Noto Sans Tamil, Noto Sans Telugu, Noto Sans Thaana, Noto Sans Thai, Noto Sans Tibetan, Noto Sans Yi, Noto Serif Armenian, Noto Serif Khmer, Noto Serif Lao, Noto Serif Thai");
+pref("font.name-list.sans-serif.x-orya", "Noto Sans Oriya, Arimo, Arial, Verdana, Noto Naskh Arabic, Noto Sans Armenian, Noto Sans Bengali, Noto Sans Buginese, Noto Sans JP Regular, Noto Sans KR Regular, Noto Sans SC Regular, Noto Sans TC Regular, Noto Sans Canadian Aboriginal, Noto Sans Cherokee, Noto Sans Devanagari, Noto Sans Ethiopic, Noto Sans Georgian, Noto Sans Gujarati, Noto Sans Gurmukhi, Noto Sans Hebrew, Noto Sans Kannada, Noto Sans Khmer, Noto Sans Lao, Noto Sans Malayalam, Noto Sans Mongolian, Noto Sans Myanmar, Noto Sans Oriya, Noto Sans Sinhala, Noto Sans Tamil, Noto Sans Telugu, Noto Sans Thaana, Noto Sans Thai, Noto Sans Tibetan, Noto Sans Yi, Noto Serif Armenian, Noto Serif Khmer, Noto Serif Lao, Noto Serif Thai");
+pref("font.name-list.sans-serif.x-sinh", "Noto Sans Sinhala, Arimo, Arial, Verdana, Noto Naskh Arabic, Noto Sans Armenian, Noto Sans Bengali, Noto Sans Buginese, Noto Sans JP Regular, Noto Sans KR Regular, Noto Sans SC Regular, Noto Sans TC Regular, Noto Sans Canadian Aboriginal, Noto Sans Cherokee, Noto Sans Devanagari, Noto Sans Ethiopic, Noto Sans Georgian, Noto Sans Gujarati, Noto Sans Gurmukhi, Noto Sans Hebrew, Noto Sans Kannada, Noto Sans Khmer, Noto Sans Lao, Noto Sans Malayalam, Noto Sans Mongolian, Noto Sans Myanmar, Noto Sans Oriya, Noto Sans Sinhala, Noto Sans Tamil, Noto Sans Telugu, Noto Sans Thaana, Noto Sans Thai, Noto Sans Tibetan, Noto Sans Yi, Noto Serif Armenian, Noto Serif Khmer, Noto Serif Lao, Noto Serif Thai");
+pref("font.name-list.sans-serif.x-tamil", "Noto Sans Tamil, Arimo, Arial, Verdana, Noto Naskh Arabic, Noto Sans Armenian, Noto Sans Bengali, Noto Sans Buginese, Noto Sans JP Regular, Noto Sans KR Regular, Noto Sans SC Regular, Noto Sans TC Regular, Noto Sans Canadian Aboriginal, Noto Sans Cherokee, Noto Sans Devanagari, Noto Sans Ethiopic, Noto Sans Georgian, Noto Sans Gujarati, Noto Sans Gurmukhi, Noto Sans Hebrew, Noto Sans Kannada, Noto Sans Khmer, Noto Sans Lao, Noto Sans Malayalam, Noto Sans Mongolian, Noto Sans Myanmar, Noto Sans Oriya, Noto Sans Sinhala, Noto Sans Tamil, Noto Sans Telugu, Noto Sans Thaana, Noto Sans Thai, Noto Sans Tibetan, Noto Sans Yi, Noto Serif Armenian, Noto Serif Khmer, Noto Serif Lao, Noto Serif Thai");
+pref("font.name-list.sans-serif.x-telu", "Noto Sans Telugu, Arimo, Arial, Verdana, Noto Naskh Arabic, Noto Sans Armenian, Noto Sans Bengali, Noto Sans Buginese, Noto Sans JP Regular, Noto Sans KR Regular, Noto Sans SC Regular, Noto Sans TC Regular, Noto Sans Canadian Aboriginal, Noto Sans Cherokee, Noto Sans Devanagari, Noto Sans Ethiopic, Noto Sans Georgian, Noto Sans Gujarati, Noto Sans Gurmukhi, Noto Sans Hebrew, Noto Sans Kannada, Noto Sans Khmer, Noto Sans Lao, Noto Sans Malayalam, Noto Sans Mongolian, Noto Sans Myanmar, Noto Sans Oriya, Noto Sans Sinhala, Noto Sans Tamil, Noto Sans Telugu, Noto Sans Thaana, Noto Sans Thai, Noto Sans Tibetan, Noto Sans Yi, Noto Serif Armenian, Noto Serif Khmer, Noto Serif Lao, Noto Serif Thai");
+pref("font.name-list.sans-serif.x-tibt", "Noto Sans Tibetan, Arimo, Arial, Verdana, Noto Naskh Arabic, Noto Sans Armenian, Noto Sans Bengali, Noto Sans Buginese, Noto Sans JP Regular, Noto Sans KR Regular, Noto Sans SC Regular, Noto Sans TC Regular, Noto Sans Canadian Aboriginal, Noto Sans Cherokee, Noto Sans Devanagari, Noto Sans Ethiopic, Noto Sans Georgian, Noto Sans Gujarati, Noto Sans Gurmukhi, Noto Sans Hebrew, Noto Sans Kannada, Noto Sans Khmer, Noto Sans Lao, Noto Sans Malayalam, Noto Sans Mongolian, Noto Sans Myanmar, Noto Sans Oriya, Noto Sans Sinhala, Noto Sans Tamil, Noto Sans Telugu, Noto Sans Thaana, Noto Sans Thai, Noto Sans Tibetan, Noto Sans Yi, Noto Serif Armenian, Noto Serif Khmer, Noto Serif Lao, Noto Serif Thai");
+pref("font.name-list.sans-serif.x-unicode", "Arimo, Arial, Verdana, Noto Naskh Arabic, Noto Sans Armenian, Noto Sans Bengali, Noto Sans Buginese, Noto Sans JP Regular, Noto Sans KR Regular, Noto Sans SC Regular, Noto Sans TC Regular, Noto Sans Canadian Aboriginal, Noto Sans Cherokee, Noto Sans Devanagari, Noto Sans Ethiopic, Noto Sans Georgian, Noto Sans Gujarati, Noto Sans Gurmukhi, Noto Sans Hebrew, Noto Sans Kannada, Noto Sans Khmer, Noto Sans Lao, Noto Sans Malayalam, Noto Sans Mongolian, Noto Sans Myanmar, Noto Sans Oriya, Noto Sans Sinhala, Noto Sans Tamil, Noto Sans Telugu, Noto Sans Thaana, Noto Sans Thai, Noto Sans Tibetan, Noto Sans Yi, Noto Serif Armenian, Noto Serif Khmer, Noto Serif Lao, Noto Serif Thai");
+pref("font.name-list.sans-serif.x-western", "Arimo, Arial, Verdana, Noto Naskh Arabic, Noto Sans Armenian, Noto Sans Bengali, Noto Sans Buginese, Noto Sans JP Regular, Noto Sans KR Regular, Noto Sans SC Regular, Noto Sans TC Regular, Noto Sans Canadian Aboriginal, Noto Sans Cherokee, Noto Sans Devanagari, Noto Sans Ethiopic, Noto Sans Georgian, Noto Sans Gujarati, Noto Sans Gurmukhi, Noto Sans Hebrew, Noto Sans Kannada, Noto Sans Khmer, Noto Sans Lao, Noto Sans Malayalam, Noto Sans Mongolian, Noto Sans Myanmar, Noto Sans Oriya, Noto Sans Sinhala, Noto Sans Tamil, Noto Sans Telugu, Noto Sans Thaana, Noto Sans Thai, Noto Sans Tibetan, Noto Sans Yi, Noto Serif Armenian, Noto Serif Khmer, Noto Serif Lao, Noto Serif Thai");
+pref("font.name-list.sans-serif.zh-CN", "Noto Sans SC Regular, Arimo, Arial, Verdana, Noto Naskh Arabic, Noto Sans Armenian, Noto Sans Bengali, Noto Sans Buginese, Noto Sans JP Regular, Noto Sans KR Regular, Noto Sans SC Regular, Noto Sans TC Regular, Noto Sans Canadian Aboriginal, Noto Sans Cherokee, Noto Sans Devanagari, Noto Sans Ethiopic, Noto Sans Georgian, Noto Sans Gujarati, Noto Sans Gurmukhi, Noto Sans Hebrew, Noto Sans Kannada, Noto Sans Khmer, Noto Sans Lao, Noto Sans Malayalam, Noto Sans Mongolian, Noto Sans Myanmar, Noto Sans Oriya, Noto Sans Sinhala, Noto Sans Tamil, Noto Sans Telugu, Noto Sans Thaana, Noto Sans Thai, Noto Sans Tibetan, Noto Sans Yi, Noto Serif Armenian, Noto Serif Khmer, Noto Serif Lao, Noto Serif Thai");
+pref("font.name-list.sans-serif.zh-HK", "Noto Sans TC Regular, Arimo, Arial, Verdana, Noto Naskh Arabic, Noto Sans Armenian, Noto Sans Bengali, Noto Sans Buginese, Noto Sans JP Regular, Noto Sans KR Regular, Noto Sans SC Regular, Noto Sans TC Regular, Noto Sans Canadian Aboriginal, Noto Sans Cherokee, Noto Sans Devanagari, Noto Sans Ethiopic, Noto Sans Georgian, Noto Sans Gujarati, Noto Sans Gurmukhi, Noto Sans Hebrew, Noto Sans Kannada, Noto Sans Khmer, Noto Sans Lao, Noto Sans Malayalam, Noto Sans Mongolian, Noto Sans Myanmar, Noto Sans Oriya, Noto Sans Sinhala, Noto Sans Tamil, Noto Sans Telugu, Noto Sans Thaana, Noto Sans Thai, Noto Sans Tibetan, Noto Sans Yi, Noto Serif Armenian, Noto Serif Khmer, Noto Serif Lao, Noto Serif Thai");
+pref("font.name-list.sans-serif.zh-TW", "Noto Sans TC Regular, Arimo, Arial, Verdana, Noto Naskh Arabic, Noto Sans Armenian, Noto Sans Bengali, Noto Sans Buginese, Noto Sans JP Regular, Noto Sans KR Regular, Noto Sans SC Regular, Noto Sans TC Regular, Noto Sans Canadian Aboriginal, Noto Sans Cherokee, Noto Sans Devanagari, Noto Sans Ethiopic, Noto Sans Georgian, Noto Sans Gujarati, Noto Sans Gurmukhi, Noto Sans Hebrew, Noto Sans Kannada, Noto Sans Khmer, Noto Sans Lao, Noto Sans Malayalam, Noto Sans Mongolian, Noto Sans Myanmar, Noto Sans Oriya, Noto Sans Sinhala, Noto Sans Tamil, Noto Sans Telugu, Noto Sans Thaana, Noto Sans Thai, Noto Sans Tibetan, Noto Sans Yi, Noto Serif Armenian, Noto Serif Khmer, Noto Serif Lao, Noto Serif Thai");
+pref("font.name-list.serif.ar", "Noto Naskh Arabic, Tinos, Georgia, Noto Serif Armenian, Noto Serif Khmer, Noto Serif Lao, Noto Serif Thai");
+pref("font.name-list.serif.el", "Tinos, Georgia, Noto Serif Armenian, Noto Serif Khmer, Noto Serif Lao, Noto Serif Thai");
+pref("font.name-list.serif.he", "Tinos, Georgia, Noto Sans Hebrew, Noto Serif Armenian, Noto Serif Khmer, Noto Serif Lao, Noto Serif Thai");
+pref("font.name-list.serif.ja", "Noto Sans JP Regular, Tinos, Georgia, Noto Serif Armenian, Noto Serif Khmer, Noto Serif Lao, Noto Serif Thai");
+pref("font.name-list.serif.ko", "Noto Sans KR Regular, Tinos, Georgia, Noto Serif Armenian, Noto Serif Khmer, Noto Serif Lao, Noto Serif Thai");
+pref("font.name-list.serif.th", "Noto Serif Thai, Tinos, Georgia, Noto Serif Armenian, Noto Serif Khmer, Noto Serif Lao, Noto Serif Thai");
+pref("font.name-list.serif.x-armn", "Noto Serif Armenian, Tinos, Georgia, Noto Serif Armenian, Noto Serif Khmer, Noto Serif Lao, Noto Serif Thai");
+pref("font.name-list.serif.x-beng", "Noto Sans Bengali, Tinos, Georgia, Noto Serif Armenian, Noto Serif Khmer, Noto Serif Lao, Noto Serif Thai");
+pref("font.name-list.serif.x-cyrillic", "Tinos, Georgia, Noto Serif Armenian, Noto Serif Khmer, Noto Serif Lao, Noto Serif Thai");
+pref("font.name-list.serif.x-devanagari", "Noto Sans Devanagari, Tinos, Georgia, Noto Serif Armenian, Noto Serif Khmer, Noto Serif Lao, Noto Serif Thai");
+pref("font.name-list.serif.x-ethi", "Noto Sans Ethiopic, Tinos, Georgia, Noto Serif Armenian, Noto Serif Khmer, Noto Serif Lao, Noto Serif Thai");
+pref("font.name-list.serif.x-geor", "Noto Sans Georgian, Tinos, Georgia, Noto Serif Armenian, Noto Serif Khmer, Noto Serif Lao, Noto Serif Thai");
+pref("font.name-list.serif.x-gujr", "Noto Sans Gujarati, Tinos, Georgia, Noto Serif Armenian, Noto Serif Khmer, Noto Serif Lao, Noto Serif Thai");
+pref("font.name-list.serif.x-guru", "Noto Sans Gurmukhi, Tinos, Georgia, Noto Serif Armenian, Noto Serif Khmer, Noto Serif Lao, Noto Serif Thai");
+pref("font.name-list.serif.x-khmr", "Noto Serif Khmer, Tinos, Georgia, Noto Serif Armenian, Noto Serif Khmer, Noto Serif Lao, Noto Serif Thai");
+pref("font.name-list.serif.x-knda", "Noto Sans Kannada, Tinos, Georgia, Noto Serif Armenian, Noto Serif Khmer, Noto Serif Lao, Noto Serif Thai");
+pref("font.name-list.serif.x-mlym", "Noto Sans Malayalam, Tinos, Georgia, Noto Serif Armenian, Noto Serif Khmer, Noto Serif Lao, Noto Serif Thai");
+pref("font.name-list.serif.x-orya", "Noto Sans Oriya, Tinos, Georgia, Noto Serif Armenian, Noto Serif Khmer, Noto Serif Lao, Noto Serif Thai");
+pref("font.name-list.serif.x-sinh", "Noto Sans Sinhala, Tinos, Georgia, Noto Serif Armenian, Noto Serif Khmer, Noto Serif Lao, Noto Serif Thai");
+pref("font.name-list.serif.x-tamil", "Noto Sans Tamil, Tinos, Georgia, Noto Serif Armenian, Noto Serif Khmer, Noto Serif Lao, Noto Serif Thai");
+pref("font.name-list.serif.x-telu", "Noto Sans Telugu, Tinos, Georgia, Noto Serif Armenian, Noto Serif Khmer, Noto Serif Lao, Noto Serif Thai");
+pref("font.name-list.serif.x-tibt", "Noto Sans Tibetan, Tinos, Georgia, Noto Serif Armenian, Noto Serif Khmer, Noto Serif Lao, Noto Serif Thai");
+pref("font.name-list.serif.x-unicode", "Tinos, Georgia, Noto Serif Armenian, Noto Serif Khmer, Noto Serif Lao, Noto Serif Thai");
+pref("font.name-list.serif.x-western", "Tinos, Georgia, Noto Serif Armenian, Noto Serif Khmer, Noto Serif Lao, Noto Serif Thai");
+pref("font.name-list.serif.zh-CN", "Noto Sans SC Regular, Tinos, Georgia, Noto Serif Armenian, Noto Serif Khmer, Noto Serif Lao, Noto Serif Thai");
+pref("font.name-list.serif.zh-HK", "Noto Sans TC Regular, Tinos, Georgia, Noto Serif Armenian, Noto Serif Khmer, Noto Serif Lao, Noto Serif Thai");
+pref("font.name-list.serif.zh-TW", "Noto Sans TC Regular, Tinos, Georgia, Noto Serif Armenian, Noto Serif Khmer, Noto Serif Lao, Noto Serif Thai");
+pref("font.name.cursive.ar", "Noto Naskh Arabic");
+pref("font.name.cursive.el", "Tinos, Georgia");
+pref("font.name.cursive.he", "Noto Sans Hebrew");
+pref("font.name.cursive.x-cyrillic", "Tinos, Georgia");
+pref("font.name.cursive.x-unicode", "Tinos, Georgia");
+pref("font.name.cursive.x-western", "Tinos, Georgia");
+pref("font.name.fantasy.ar", "Noto Naskh Arabic");
+pref("font.name.fantasy.el", "Tinos, Georgia");
+pref("font.name.fantasy.he", "Noto Sans Hebrew");
+pref("font.name.fantasy.x-cyrillic", "Tinos, Georgia");
+pref("font.name.fantasy.x-unicode", "Tinos, Georgia");
+pref("font.name.fantasy.x-western", "Tinos, Georgia");
+pref("font.name.monospace.ar", "Noto Naskh Arabic");
+pref("font.name.monospace.el", "Tinos, Georgia");
+pref("font.name.monospace.he", "Noto Sans Hebrew");
+pref("font.name.monospace.ja", "Noto Sans JP Regular");
+pref("font.name.monospace.ko", "Noto Sans KR Regular");
+pref("font.name.monospace.my", "Noto Sans Myanmar");
+pref("font.name.monospace.th", "Noto Sans Thai");
+pref("font.name.monospace.x-armn", "Noto Sans Armenian");
+pref("font.name.monospace.x-beng", "Noto Sans Bengali");
+pref("font.name.monospace.x-cyrillic", "Cousine, Courier, Courier New");
+pref("font.name.monospace.x-devanagari", "Noto Sans Devanagari");
+pref("font.name.monospace.x-ethi", "Noto Sans Ethiopic");
+pref("font.name.monospace.x-geor", "Noto Sans Georgian");
+pref("font.name.monospace.x-gujr", "Noto Sans Gujarati");
+pref("font.name.monospace.x-guru", "Noto Sans Gurmukhi");
+pref("font.name.monospace.x-khmr", "Noto Sans Khmer");
+pref("font.name.monospace.x-knda", "Noto Sans Kannada");
+pref("font.name.monospace.x-mlym", "Noto Sans Malayalam");
+pref("font.name.monospace.x-orya", "Noto Sans Oriya");
+pref("font.name.monospace.x-sinh", "Noto Sans Sinhala");
+pref("font.name.monospace.x-tamil", "Noto Sans Tamil");
+pref("font.name.monospace.x-telu", "Noto Sans Telugu");
+pref("font.name.monospace.x-tibt", "Noto Sans Tibetan");
+pref("font.name.monospace.x-unicode", "Cousine, Courier, Courier New");
+pref("font.name.monospace.x-western", "Cousine, Courier, Courier New");
+pref("font.name.monospace.zh-CN", "Noto Sans SC Regular");
+pref("font.name.monospace.zh-HK", "Noto Sans TC Regular");
+pref("font.name.monospace.zh-TW", "Noto Sans TC Regular");
+pref("font.name.sans-serif.ar", "Noto Naskh Arabic");
+pref("font.name.sans-serif.el", "Arimo, Arial, Verdana");
+pref("font.name.sans-serif.he", "Noto Sans Hebrew");
+pref("font.name.sans-serif.ja", "Noto Sans JP Regular");
+pref("font.name.sans-serif.ko", "Noto Sans KR Regular");
+pref("font.name.sans-serif.th", "Noto Sans Thai");
+pref("font.name.sans-serif.x-armn", "Noto Sans Armenian");
+pref("font.name.sans-serif.x-beng", "Noto Sans Bengali");
+pref("font.name.sans-serif.x-cyrillic", "Arimo, Arial, Verdana");
+pref("font.name.sans-serif.x-devanagari", "Noto Sans Devanagari");
+pref("font.name.sans-serif.x-ethi", "Noto Sans Ethiopic");
+pref("font.name.sans-serif.x-geor", "Noto Sans Georgian");
+pref("font.name.sans-serif.x-gujr", "Noto Sans Gujarati");
+pref("font.name.sans-serif.x-guru", "Noto Sans Gurmukhi");
+pref("font.name.sans-serif.x-khmr", "Noto Sans Khmer");
+pref("font.name.sans-serif.x-knda", "Noto Sans Kannada");
+pref("font.name.sans-serif.x-mlym", "Noto Sans Malayalam");
+pref("font.name.sans-serif.x-orya", "Noto Sans Oriya");
+pref("font.name.sans-serif.x-sinh", "Noto Sans Sinhala");
+pref("font.name.sans-serif.x-tamil", "Noto Sans Tamil");
+pref("font.name.sans-serif.x-telu", "Noto Sans Telugu");
+pref("font.name.sans-serif.x-tibt", "Noto Sans Tibetan");
+pref("font.name.sans-serif.x-unicode", "Arimo, Arial, Verdana");
+pref("font.name.sans-serif.x-western", "Arimo, Arial, Verdana");
+pref("font.name.sans-serif.zh-CN", "Noto Sans SC Regular");
+pref("font.name.sans-serif.zh-HK", "Noto Sans TC Regular");
+pref("font.name.sans-serif.zh-TW", "Noto Sans TC Regular");
+pref("font.name.sans.my", "Noto Sans Myanmar");
+pref("font.name.serif.ar", "Noto Naskh Arabic");
+pref("font.name.serif.el", "Tinos, Georgia");
+pref("font.name.serif.he", "Noto Sans Hebrew");
+pref("font.name.serif.ja", "Noto Sans JP Regular");
+pref("font.name.serif.ko", "Noto Sans KR Regular");
+pref("font.name.serif.my", "Noto Sans Myanmar");
+pref("font.name.serif.th", "Noto Serif Thai");
+pref("font.name.serif.x-armn", "Noto Serif Armenian");
+pref("font.name.serif.x-beng", "Noto Sans Bengali");
+pref("font.name.serif.x-cyrillic", "Tinos, Georgia");
+pref("font.name.serif.x-devanagari", "Noto Sans Devanagari");
+pref("font.name.serif.x-ethi", "Noto Sans Ethiopic");
+pref("font.name.serif.x-geor", "Noto Sans Georgian");
+pref("font.name.serif.x-gujr", "Noto Sans Gujarati");
+pref("font.name.serif.x-guru", "Noto Sans Gurmukhi");
+pref("font.name.serif.x-khmr", "Noto Serif Khmer");
+pref("font.name.serif.x-knda", "Noto Sans Kannada");
+pref("font.name.serif.x-mlym", "Noto Sans Malayalam");
+pref("font.name.serif.x-orya", "Noto Sans Oriya");
+pref("font.name.serif.x-sinh", "Noto Sans Sinhala");
+pref("font.name.serif.x-tamil", "Noto Sans Tamil");
+pref("font.name.serif.x-telu", "Noto Sans Telugu");
+pref("font.name.serif.x-tibt", "Noto Sans Tibetan");
+pref("font.name.serif.x-unicode", "Tinos, Georgia");
+pref("font.name.serif.x-western", "Tinos, Georgia");
+pref("font.name.serif.zh-CN", "Noto Sans SC Regular");
+pref("font.name.serif.zh-HK", "Noto Sans TC Regular");
+pref("font.name.serif.zh-TW", "Noto Sans TC Regular");
+#endif
+#endif
diff --git a/browser/app/profile/firefox.js b/browser/app/profile/firefox.js
index 479c68efdd8c..b04fd2dd30f0 100644
--- a/browser/app/profile/firefox.js
+++ b/browser/app/profile/firefox.js
@@ -53,9 +53,9 @@ pref("extensions.recommendations.themeRecommendationUrl", "https://color.firefox
pref("extensions.update.autoUpdateDefault", true);
-// Check AUS for system add-on updates.
-pref("extensions.systemAddon.update.url", "https://aus5.mozilla.org/update/3/SystemAddons/%VERSION%/%BUILD_ID%/%BUILD_…");
-pref("extensions.systemAddon.update.enabled", true);
+// No AUS check for system add-on updates for Tor Browser users.
+pref("extensions.systemAddon.update.url", "");
+pref("extensions.systemAddon.update.enabled", false);
// Disable add-ons that are not installed by the user in all scopes by default.
// See the SCOPE constants in AddonManager.jsm for values to use here.
diff --git a/browser/installer/package-manifest.in b/browser/installer/package-manifest.in
index e011b74cc4b4..7deaf1b51f9a 100644
--- a/browser/installer/package-manifest.in
+++ b/browser/installer/package-manifest.in
@@ -292,6 +292,7 @@
@RESPATH@/browser/defaults/settings/pinning
@RESPATH@/browser/defaults/settings/main
@RESPATH@/browser/defaults/settings/security-state
+@RESPATH@/browser/@PREF_DIR@/000-tor-browser.js
; Warning: changing the path to channel-prefs.js can cause bugs (Bug 756325)
; Technically this is an app pref file, but we are keeping it in the original
diff --git a/browser/moz.build b/browser/moz.build
index cfbfea4f31f2..19977e036fba 100644
--- a/browser/moz.build
+++ b/browser/moz.build
@@ -53,6 +53,7 @@ if CONFIG['MOZ_GPSD']:
# These files are specified in this moz.build to pick up DIST_SUBDIR as set in
# this directory, which is un-set in browser/app.
JS_PREFERENCE_PP_FILES += [
+ 'app/profile/000-tor-browser.js',
'app/profile/firefox.js',
]
FINAL_TARGET_FILES.defaults += ['app/permissions']
diff --git a/mobile/android/app/000-tor-browser-android.js b/mobile/android/app/000-tor-browser-android.js
new file mode 100644
index 000000000000..61c8a0cd7fa1
--- /dev/null
+++ b/mobile/android/app/000-tor-browser-android.js
@@ -0,0 +1,47 @@
+// Import all prefs from the canonical file
+// We override mobile-specific prefs below
+// Tor Browser for Android
+// Do not edit this file.
+
+#include ../../../browser/app/profile/000-tor-browser.js
+
+// Space separated list of URLs that are allowed to send objects (instead of
+// only strings) through webchannels. This list is duplicated in browser/app/profile/firefox.js
+pref("webchannel.allowObject.urlWhitelist", "");
+
+// Disable browser auto updaters
+pref("app.update.auto", false);
+pref("browser.startup.homepage_override.mstone", "ignore");
+
+// Clear data on quit
+pref("privacy.clearOnShutdown.cache", true);
+pref("privacy.clearOnShutdown.cookies",true);
+pref("privacy.clearOnShutdown.downloads",true);
+pref("privacy.clearOnShutdown.formdata",true);
+pref("privacy.clearOnShutdown.history",true);
+pref("privacy.clearOnShutdown.offlineApps",true);
+pref("privacy.clearOnShutdown.passwords",true);
+pref("privacy.clearOnShutdown.sessions",true);
+pref("privacy.clearOnShutdown.siteSettings",true);
+
+// controls if we want camera support
+pref("media.realtime_decoder.enabled", false);
+
+// Enable touch events on Android (highlighting text, etc)
+pref("dom.w3c_touch_events.enabled", 2);
+
+// Ensure that pointer events are disabled
+pref("dom.w3c_pointer_events.multiprocess.android.enabled", false);
+
+// No HLS support for now due to browser freezing, see: #29859.
+pref("media.hls.enabled", false);
+
+// Inherit locale from the OS, used for multi-locale builds
+pref("intl.locale.requested", "");
+
+// Disable WebAuthn. It requires Google Play Services, so it isn't
+// available, but avoid any potential problems.
+pref("security.webauth.webauthn_enable_android_fido2", false);
+
+// Disable the External App Blocker on Android
+pref("extensions.torbutton.launch_warning", false);
diff --git a/mobile/android/app/geckoview-prefs.js b/mobile/android/app/geckoview-prefs.js
index 3d3871975a28..826970425362 100644
--- a/mobile/android/app/geckoview-prefs.js
+++ b/mobile/android/app/geckoview-prefs.js
@@ -91,3 +91,5 @@ pref("toolkit.autocomplete.delegate", true);
// Android doesn't support the new sync storage yet, we will have our own in
// Bug 1625257.
pref("webextensions.storage.sync.kinto", true);
+
+#include 000-tor-browser-android.js
diff --git a/mobile/android/app/mobile.js b/mobile/android/app/mobile.js
index c0f0a0a2dfd8..6c72bc2ed2d7 100644
--- a/mobile/android/app/mobile.js
+++ b/mobile/android/app/mobile.js
@@ -399,7 +399,11 @@ pref("app.update.timerMinimumDelay", 30); // seconds
// used by update service to decide whether or not to
// automatically download an update
pref("app.update.autodownload", "wifi");
+#ifdef TOR_BROWSER_VERSION
+pref("app.update.url.android", "");
+#else
pref("app.update.url.android", "https://aus5.mozilla.org/update/4/%PRODUCT%/%VERSION%/%BUILD_ID%/%BUILD_TAR…");
+#endif
#ifdef MOZ_UPDATER
/* prefs used specifically for updating the app */
diff --git a/mobile/android/app/moz.build b/mobile/android/app/moz.build
index 65963fe448eb..4075e8a9d2c4 100644
--- a/mobile/android/app/moz.build
+++ b/mobile/android/app/moz.build
@@ -17,6 +17,7 @@ if CONFIG['MOZ_PKG_SPECIAL']:
DEFINES['MOZ_PKG_SPECIAL'] = CONFIG['MOZ_PKG_SPECIAL']
JS_PREFERENCE_PP_FILES += [
+ '000-tor-browser-android.js',
'mobile.js',
]
diff --git a/taskcluster/ci/source-test/mozlint.yml b/taskcluster/ci/source-test/mozlint.yml
index 6e3373dee6ec..42067fcf14a0 100644
--- a/taskcluster/ci/source-test/mozlint.yml
+++ b/taskcluster/ci/source-test/mozlint.yml
@@ -135,7 +135,9 @@ lintpref:
files-changed:
- 'modules/libpref/init/all.js'
- 'modules/libpref/init/StaticPrefList.yaml'
+ - 'browser/app/profile/000-tor-browser.js'
- 'browser/app/profile/firefox.js'
+ - 'mobile/android/app/000-tor-browser-android.js'
- 'mobile/android/app/mobile.js'
- 'devtools/client/preferences/debugger.js'
- 'mobile/android/app/geckoview-prefs.js'
1
0
[tor-browser/tor-browser-78.12.0esr-11.0-1] Bug 40166: Disable security.certerrors.mitm.auto_enable_enterprise_roots
by boklm@torproject.org 14 Jul '21
by boklm@torproject.org 14 Jul '21
14 Jul '21
commit b4ac13e68aade0c108ccf44ce00d7cba8411cfb6
Author: Alex Catarineu <acat(a)torproject.org>
Date: Fri Oct 9 12:55:35 2020 +0200
Bug 40166: Disable security.certerrors.mitm.auto_enable_enterprise_roots
---
browser/app/profile/000-tor-browser.js | 3 +++
browser/components/BrowserGlue.jsm | 14 ++++++++++++++
2 files changed, 17 insertions(+)
diff --git a/browser/app/profile/000-tor-browser.js b/browser/app/profile/000-tor-browser.js
index 2db11b1ea3d7..760c405d06a6 100644
--- a/browser/app/profile/000-tor-browser.js
+++ b/browser/app/profile/000-tor-browser.js
@@ -325,6 +325,9 @@ pref("security.enterprise_roots.enabled", false);
// Don't ping Mozilla for MitM detection, see bug 32321
pref("security.certerrors.mitm.priming.enabled", false);
+// Don't automatically enable enterprise roots, see bug 40166
+pref("security.certerrors.mitm.auto_enable_enterprise_roots", false);
+
// Disable the language pack signing check for now on macOS, see #31942
#ifdef XP_MACOSX
pref("extensions.langpacks.signatures.required", false);
diff --git a/browser/components/BrowserGlue.jsm b/browser/components/BrowserGlue.jsm
index 057a2121533c..3750230a250b 100644
--- a/browser/components/BrowserGlue.jsm
+++ b/browser/components/BrowserGlue.jsm
@@ -1319,6 +1319,20 @@ BrowserGlue.prototype = {
// handle any UI migration
this._migrateUI();
+ // Clear possibly auto enabled enterprise_roots prefs (see bug 40166)
+ if (
+ !Services.prefs.getBoolPref(
+ "security.certerrors.mitm.auto_enable_enterprise_roots"
+ ) &&
+ Services.prefs.getBoolPref(
+ "security.enterprise_roots.auto-enabled",
+ false
+ )
+ ) {
+ Services.prefs.clearUserPref("security.enterprise_roots.enabled");
+ Services.prefs.clearUserPref("security.enterprise_roots.auto-enabled");
+ }
+
if (!Services.prefs.prefHasUserValue(PREF_PDFJS_ISDEFAULT_CACHE_STATE)) {
PdfJs.checkIsDefault(this._isNewProfile);
}
1
0
[tor-browser/tor-browser-78.12.0esr-11.0-1] Bug 40091: Load HTTPS Everywhere as a builtin addon in desktop
by boklm@torproject.org 14 Jul '21
by boklm@torproject.org 14 Jul '21
14 Jul '21
commit 74b073476b2edd63dac7f6286c794aeae8f68018
Author: Alex Catarineu <acat(a)torproject.org>
Date: Fri Sep 4 12:34:35 2020 +0200
Bug 40091: Load HTTPS Everywhere as a builtin addon in desktop
This loads HTTPS Everywhere as a builtin addon from a hardcoded
resource:// URI in desktop. It also ensures that the non-builtin
HTTPS Everywhere addon is always uninstalled on browser startup.
The reason of making this desktop-only is that there are some issues
when installing a builtin extension from geckoview side, making
the extension not available on first startup. So, at least for
now we handle the Fenix case separately. See #40118 for a followup
for investigating these.
---
browser/components/BrowserGlue.jsm | 37 ++++++++++++++++++++++
toolkit/components/extensions/Extension.jsm | 14 ++++++--
.../mozapps/extensions/internal/XPIProvider.jsm | 13 ++++++++
3 files changed, 61 insertions(+), 3 deletions(-)
diff --git a/browser/components/BrowserGlue.jsm b/browser/components/BrowserGlue.jsm
index ec38d0ca8b33..057a2121533c 100644
--- a/browser/components/BrowserGlue.jsm
+++ b/browser/components/BrowserGlue.jsm
@@ -56,6 +56,13 @@ XPCOMUtils.defineLazyServiceGetter(
"nsIPushService"
);
+XPCOMUtils.defineLazyServiceGetters(this, {
+ resProto: [
+ "@mozilla.org/network/protocol;1?name=resource",
+ "nsISubstitutingProtocolHandler",
+ ],
+});
+
const PREF_PDFJS_ISDEFAULT_CACHE_STATE = "pdfjs.enabledCache.state";
/**
@@ -675,6 +682,7 @@ XPCOMUtils.defineLazyModuleGetters(this, {
"resource://gre/modules/ContextualIdentityService.jsm",
Corroborate: "resource://gre/modules/Corroborate.jsm",
Discovery: "resource:///modules/Discovery.jsm",
+ ExtensionData: "resource://gre/modules/Extension.jsm",
ExtensionsUI: "resource:///modules/ExtensionsUI.jsm",
FirefoxMonitor: "resource:///modules/FirefoxMonitor.jsm",
FxAccounts: "resource://gre/modules/FxAccounts.jsm",
@@ -1330,6 +1338,35 @@ BrowserGlue.prototype = {
"resource:///modules/themes/dark/"
);
+ // Install https-everywhere builtin addon if needed.
+ (async () => {
+ const HTTPS_EVERYWHERE_ID = "https-everywhere-eff(a)eff.org";
+ const HTTPS_EVERYWHERE_BUILTIN_URL =
+ "resource://torbutton/content/extensions/https-everywhere/";
+ // This does something similar as GeckoViewWebExtension.jsm: it tries
+ // to load the manifest to retrieve the version of the builtin and
+ // compares it to the currently installed one to see whether we need
+ // to install or not. Here we delegate that to
+ // AddonManager.maybeInstallBuiltinAddon.
+ try {
+ const resolvedURI = Services.io.newURI(
+ resProto.resolveURI(Services.io.newURI(HTTPS_EVERYWHERE_BUILTIN_URL))
+ );
+ const extensionData = new ExtensionData(resolvedURI);
+ const manifest = await extensionData.loadManifest();
+
+ await AddonManager.maybeInstallBuiltinAddon(
+ HTTPS_EVERYWHERE_ID,
+ manifest.version,
+ HTTPS_EVERYWHERE_BUILTIN_URL
+ );
+ } catch (e) {
+ const log = Log.repository.getLogger("HttpsEverywhereBuiltinLoader");
+ log.addAppender(new Log.ConsoleAppender(new Log.BasicFormatter()));
+ log.error("Could not install https-everywhere extension", e);
+ }
+ })();
+
if (AppConstants.MOZ_NORMANDY) {
Normandy.init();
}
diff --git a/toolkit/components/extensions/Extension.jsm b/toolkit/components/extensions/Extension.jsm
index 876e636be3db..7dbd888b1710 100644
--- a/toolkit/components/extensions/Extension.jsm
+++ b/toolkit/components/extensions/Extension.jsm
@@ -211,6 +211,7 @@ const LOGGER_ID_BASE = "addons.webextension.";
const UUID_MAP_PREF = "extensions.webextensions.uuids";
const LEAVE_STORAGE_PREF = "extensions.webextensions.keepStorageOnUninstall";
const LEAVE_UUID_PREF = "extensions.webextensions.keepUuidOnUninstall";
+const PERSISTENT_EXTENSIONS = new Set(["https-everywhere-eff(a)eff.org"]);
const COMMENT_REGEXP = new RegExp(
String.raw`
@@ -331,7 +332,10 @@ var ExtensionAddonObserver = {
return;
}
- if (!Services.prefs.getBoolPref(LEAVE_STORAGE_PREF, false)) {
+ if (
+ !Services.prefs.getBoolPref(LEAVE_STORAGE_PREF, false) &&
+ !PERSISTENT_EXTENSIONS.has(addon.id)
+ ) {
// Clear browser.storage.local backends.
AsyncShutdown.profileChangeTeardown.addBlocker(
`Clear Extension Storage ${addon.id} (File Backend)`,
@@ -384,7 +388,10 @@ var ExtensionAddonObserver = {
ExtensionPermissions.removeAll(addon.id);
- if (!Services.prefs.getBoolPref(LEAVE_UUID_PREF, false)) {
+ if (
+ !Services.prefs.getBoolPref(LEAVE_UUID_PREF, false) &&
+ !PERSISTENT_EXTENSIONS.has(addon.id)
+ ) {
// Clear the entry in the UUID map
UUIDMap.remove(addon.id);
}
@@ -2474,7 +2481,8 @@ class Extension extends ExtensionData {
);
} else if (
this.startupReason === "ADDON_INSTALL" &&
- !Services.prefs.getBoolPref(LEAVE_STORAGE_PREF, false)
+ !Services.prefs.getBoolPref(LEAVE_STORAGE_PREF, false) &&
+ !PERSISTENT_EXTENSIONS.has(this.id)
) {
// If the extension has been just installed, set it as migrated,
// because there will not be any data to migrate.
diff --git a/toolkit/mozapps/extensions/internal/XPIProvider.jsm b/toolkit/mozapps/extensions/internal/XPIProvider.jsm
index 794c206fb453..dc5362bce3d8 100644
--- a/toolkit/mozapps/extensions/internal/XPIProvider.jsm
+++ b/toolkit/mozapps/extensions/internal/XPIProvider.jsm
@@ -1491,6 +1491,19 @@ var XPIStates = {
continue;
}
+ // Uninstall HTTPS Everywhere if it is installed in the user profile.
+ if (
+ id === "https-everywhere-eff(a)eff.org" &&
+ loc.name === KEY_APP_PROFILE
+ ) {
+ logger.debug(
+ "Uninstalling the HTTPS Everywhere extension from user profile."
+ );
+ loc.installer.uninstallAddon(id);
+ changed = true;
+ continue;
+ }
+
let xpiState = loc.get(id);
if (!xpiState) {
// If the location is not supported for sideloading, skip new
1
0
[tor-browser/tor-browser-78.12.0esr-11.0-1] Bug 40475: Include clearing CORS preflight cache
by boklm@torproject.org 14 Jul '21
by boklm@torproject.org 14 Jul '21
14 Jul '21
commit d57b416593b4e4588c387374a230cc4a3f25ce87
Author: Matthew Finkel <sysrqb(a)torproject.org>
Date: Sun Jun 6 20:32:23 2021 +0000
Bug 40475: Include clearing CORS preflight cache
---
netwerk/protocol/http/nsCORSListenerProxy.cpp | 7 +++++++
netwerk/protocol/http/nsCORSListenerProxy.h | 1 +
netwerk/protocol/http/nsHttpHandler.cpp | 2 ++
3 files changed, 10 insertions(+)
diff --git a/netwerk/protocol/http/nsCORSListenerProxy.cpp b/netwerk/protocol/http/nsCORSListenerProxy.cpp
index 76870e6cea3f..6d2e160c2a9b 100644
--- a/netwerk/protocol/http/nsCORSListenerProxy.cpp
+++ b/netwerk/protocol/http/nsCORSListenerProxy.cpp
@@ -346,6 +346,13 @@ void nsCORSListenerProxy::Shutdown() {
sPreflightCache = nullptr;
}
+/* static */
+void nsCORSListenerProxy::Clear() {
+ if (sPreflightCache) {
+ sPreflightCache->Clear();
+ }
+}
+
nsCORSListenerProxy::nsCORSListenerProxy(nsIStreamListener* aOuter,
nsIPrincipal* aRequestingPrincipal,
bool aWithCredentials)
diff --git a/netwerk/protocol/http/nsCORSListenerProxy.h b/netwerk/protocol/http/nsCORSListenerProxy.h
index 8c0df2e0ff28..3f76be33f209 100644
--- a/netwerk/protocol/http/nsCORSListenerProxy.h
+++ b/netwerk/protocol/http/nsCORSListenerProxy.h
@@ -54,6 +54,7 @@ class nsCORSListenerProxy final : public nsIStreamListener,
NS_DECL_NSITHREADRETARGETABLESTREAMLISTENER
static void Shutdown();
+ static void Clear();
[[nodiscard]] nsresult Init(nsIChannel* aChannel,
DataURIHandling aAllowDataURI);
diff --git a/netwerk/protocol/http/nsHttpHandler.cpp b/netwerk/protocol/http/nsHttpHandler.cpp
index d5e2c61dbec9..c6cb95ca7fcc 100644
--- a/netwerk/protocol/http/nsHttpHandler.cpp
+++ b/netwerk/protocol/http/nsHttpHandler.cpp
@@ -10,6 +10,7 @@
#include "prsystem.h"
#include "AltServiceChild.h"
+#include "nsCORSListenerProxy.h"
#include "nsError.h"
#include "nsHttp.h"
#include "nsHttpHandler.h"
@@ -2290,6 +2291,7 @@ nsHttpHandler::Observe(nsISupports* subject, const char* topic,
mAltSvcCache->ClearAltServiceMappings();
}
}
+ nsCORSListenerProxy::Clear();
} else if (!strcmp(topic, NS_NETWORK_LINK_TOPIC)) {
nsAutoCString converted = NS_ConvertUTF16toUTF8(data);
if (!strcmp(converted.get(), NS_NETWORK_LINK_DATA_CHANGED)) {
1
0
[tor-browser/tor-browser-78.12.0esr-11.0-1] Bug 1673237 - Always allow SVGs on about: pages r=acat, tjr, emilio
by boklm@torproject.org 14 Jul '21
by boklm@torproject.org 14 Jul '21
14 Jul '21
commit b89147a8fe0f5b741d8cac4de45c3ab3decce37b
Author: sanketh <me(a)snkth.com>
Date: Tue Nov 3 17:34:20 2020 +0000
Bug 1673237 - Always allow SVGs on about: pages r=acat,tjr,emilio
- Updated layout/svg/tests/test_disabled.html to ensure that this doesn't allow
rendering SVGs on about:blank and about:srcdoc.
Differential Revision: https://phabricator.services.mozilla.com/D95139
---
dom/base/nsNodeInfoManager.cpp | 18 ++++++++++-------
layout/svg/tests/file_disabled_iframe.html | 31 +++++++++++++++++++++++++++++-
2 files changed, 41 insertions(+), 8 deletions(-)
diff --git a/dom/base/nsNodeInfoManager.cpp b/dom/base/nsNodeInfoManager.cpp
index b0534b661a23..8bc6b0ba2bd6 100644
--- a/dom/base/nsNodeInfoManager.cpp
+++ b/dom/base/nsNodeInfoManager.cpp
@@ -352,9 +352,12 @@ void nsNodeInfoManager::RemoveNodeInfo(NodeInfo* aNodeInfo) {
MOZ_ASSERT(ret, "Can't find mozilla::dom::NodeInfo to remove!!!");
}
-static bool IsSystemOrAddonPrincipal(nsIPrincipal* aPrincipal) {
+static bool IsSystemOrAddonOrAboutPrincipal(nsIPrincipal* aPrincipal) {
return aPrincipal->IsSystemPrincipal() ||
- BasePrincipal::Cast(aPrincipal)->AddonPolicy();
+ BasePrincipal::Cast(aPrincipal)->AddonPolicy() ||
+ // NOTE: about:blank and about:srcdoc inherit the principal of their
+ // parent, so aPrincipal->SchemeIs("about") returns false for them.
+ aPrincipal->SchemeIs("about");
}
bool nsNodeInfoManager::InternalSVGEnabled() {
@@ -375,17 +378,18 @@ bool nsNodeInfoManager::InternalSVGEnabled() {
}
// We allow SVG (regardless of the pref) if this is a system or add-on
- // principal, or if this load was requested for a system or add-on principal
- // (e.g. a remote image being served as part of system or add-on UI)
+ // principal or about: page, or if this load was requested for a system or
+ // add-on principal or about: page (e.g. a remote image being served as part
+ // of system or add-on UI or about: page)
bool conclusion =
- (SVGEnabled || IsSystemOrAddonPrincipal(mPrincipal) ||
+ (SVGEnabled || IsSystemOrAddonOrAboutPrincipal(mPrincipal) ||
(loadInfo &&
(loadInfo->GetExternalContentPolicyType() ==
nsIContentPolicy::TYPE_IMAGE ||
loadInfo->GetExternalContentPolicyType() ==
nsIContentPolicy::TYPE_OTHER) &&
- (IsSystemOrAddonPrincipal(loadInfo->GetLoadingPrincipal()) ||
- IsSystemOrAddonPrincipal(loadInfo->TriggeringPrincipal()))));
+ (IsSystemOrAddonOrAboutPrincipal(loadInfo->GetLoadingPrincipal()) ||
+ IsSystemOrAddonOrAboutPrincipal(loadInfo->TriggeringPrincipal()))));
mSVGEnabled = Some(conclusion);
return conclusion;
}
diff --git a/layout/svg/tests/file_disabled_iframe.html b/layout/svg/tests/file_disabled_iframe.html
index 6feae3024730..55eda75fdefb 100644
--- a/layout/svg/tests/file_disabled_iframe.html
+++ b/layout/svg/tests/file_disabled_iframe.html
@@ -48,5 +48,34 @@
t.firstChild.firstChild.textContent = "1&2<3>4\xA0";
is(t.innerHTML, '<svg><style>1&2<3>4 \u003C/style></svg>');
- SimpleTest.finish();
+ //
+ // Tests for Bug 1673237
+ //
+
+ // This test fails if about:blank renders SVGs
+ t.innerHTML = null;
+ var iframe = document.createElement("iframe");
+ iframe.setAttribute("src", "about:blank")
+ t.appendChild(iframe);
+ iframe.appendChild(document.createElementNS("http://www.w3.org/2000/svg", "svg:svg"));
+ iframe.firstChild.textContent = "<foo>";
+ is(iframe.innerHTML, "<svg:svg><foo></svg:svg>");
+
+ // This test fails if about:blank renders SVGs
+ var win = window.open("about:blank");
+ win.document.body.appendChild(document.createElementNS("http://www.w3.org/2000/svg", "svg:svg"))
+ win.document.body.firstChild.textContent = "<foo>";
+ is(win.document.body.innerHTML, "<svg:svg><foo></svg:svg>");
+ win.close();
+
+ // This test fails if about:srcdoc renders SVGs
+ t.innerHTML = null;
+ iframe = document.createElement("iframe");
+ iframe.srcdoc = "<svg:svg></svg:svg>";
+ iframe.onload = function() {
+ iframe.contentDocument.body.firstChild.textContent = "<foo>";
+ is(iframe.contentDocument.body.innerHTML, "<svg:svg><foo></svg:svg>");
+ SimpleTest.finish();
+ }
+ t.appendChild(iframe);
</script>
1
0
[tor-browser/tor-browser-78.12.0esr-11.0-1] Bug 1650281 - P2: Make sure `gCombinedSizes` won't be underflowed r=gerald
by boklm@torproject.org 14 Jul '21
by boklm@torproject.org 14 Jul '21
14 Jul '21
commit 97e511582abbe606603b737790ec700864c41468
Author: Chun-Min Chang <chun.m.chang(a)gmail.com>
Date: Tue Jul 21 23:39:14 2020 +0000
Bug 1650281 - P2: Make sure `gCombinedSizes` won't be underflowed r=gerald
In any case, `gCombinedSizes` should be larger than or equal to the
buffer within `MemoryClockCache`.
Differential Revision: https://phabricator.services.mozilla.com/D84274
---
dom/media/MemoryBlockCache.cpp | 1 +
1 file changed, 1 insertion(+)
diff --git a/dom/media/MemoryBlockCache.cpp b/dom/media/MemoryBlockCache.cpp
index bf073e6769d0..2848a3f3812c 100644
--- a/dom/media/MemoryBlockCache.cpp
+++ b/dom/media/MemoryBlockCache.cpp
@@ -52,6 +52,7 @@ MemoryBlockCache::MemoryBlockCache(int64_t aContentLength)
}
MemoryBlockCache::~MemoryBlockCache() {
+ MOZ_ASSERT(gCombinedSizes >= mBuffer.Length());
size_t sizes = static_cast<size_t>(gCombinedSizes -= mBuffer.Length());
LOG("~MemoryBlockCache() - destroying buffer of size %zu; combined sizes now "
"%zu",
1
0
[tor-browser/tor-browser-78.12.0esr-11.0-1] 40209: Implement Basic Crypto Safety
by boklm@torproject.org 14 Jul '21
by boklm@torproject.org 14 Jul '21
14 Jul '21
commit 0dc2c5df8b918f561fc0e56110a44cd25788c927
Author: sanketh <me(a)snkth.com>
Date: Mon Feb 8 20:12:44 2021 -0500
40209: Implement Basic Crypto Safety
Adds a CryptoSafety actor which detects when you've copied a crypto
address from a HTTP webpage and shows a warning.
Closes #40209.
Bug 40428: Fix string attribute names
---
browser/actors/CryptoSafetyChild.jsm | 87 ++++++++++++++++
browser/actors/CryptoSafetyParent.jsm | 142 +++++++++++++++++++++++++++
browser/actors/moz.build | 2 +
browser/base/content/popup-notifications.inc | 14 +++
browser/components/BrowserGlue.jsm | 17 ++++
browser/modules/TorStrings.jsm | 48 +++++++++
browser/themes/shared/browser.inc.css | 5 +
toolkit/content/license.html | 32 ++++++
toolkit/modules/Bech32Decode.jsm | 103 +++++++++++++++++++
toolkit/modules/moz.build | 1 +
10 files changed, 451 insertions(+)
diff --git a/browser/actors/CryptoSafetyChild.jsm b/browser/actors/CryptoSafetyChild.jsm
new file mode 100644
index 000000000000..87ff261d4915
--- /dev/null
+++ b/browser/actors/CryptoSafetyChild.jsm
@@ -0,0 +1,87 @@
+/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
+/* Copyright (c) 2020, The Tor Project, Inc.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * 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/. */
+
+var EXPORTED_SYMBOLS = ["CryptoSafetyChild"];
+
+const { Bech32Decode } = ChromeUtils.import(
+ "resource://gre/modules/Bech32Decode.jsm"
+);
+
+const { XPCOMUtils } = ChromeUtils.import(
+ "resource://gre/modules/XPCOMUtils.jsm"
+);
+
+const kPrefCryptoSafety = "security.cryptoSafety";
+
+XPCOMUtils.defineLazyPreferenceGetter(
+ this,
+ "isCryptoSafetyEnabled",
+ kPrefCryptoSafety,
+ true /* defaults to true */
+);
+
+function looksLikeCryptoAddress(s) {
+ // P2PKH and P2SH addresses
+ // https://stackoverflow.com/a/24205650
+ const bitcoinAddr = /^[13][a-km-zA-HJ-NP-Z1-9]{25,39}$/;
+ if (bitcoinAddr.test(s)) {
+ return true;
+ }
+
+ // Bech32 addresses
+ if (Bech32Decode(s) !== null) {
+ return true;
+ }
+
+ // regular addresses
+ const etherAddr = /^0x[a-fA-F0-9]{40}$/;
+ if (etherAddr.test(s)) {
+ return true;
+ }
+
+ // t-addresses
+ // https://www.reddit.com/r/zec/comments/8mxj6x/simple_regex_to_validate_a_zca…
+ const zcashAddr = /^t1[a-zA-Z0-9]{33}$/;
+ if (zcashAddr.test(s)) {
+ return true;
+ }
+
+ // Standard, Integrated, and 256-bit Integrated addresses
+ // https://monero.stackexchange.com/a/10627
+ const moneroAddr = /^4(?:[0-9AB]|[1-9A-HJ-NP-Za-km-z]{12}(?:[1-9A-HJ-NP-Za-km-z]{30})?)[1-9A-HJ-NP-Za-km-z]{93}$/;
+ if (moneroAddr.test(s)) {
+ return true;
+ }
+
+ return false;
+}
+
+class CryptoSafetyChild extends JSWindowActorChild {
+ handleEvent(event) {
+ if (isCryptoSafetyEnabled) {
+ // Ignore non-HTTP addresses
+ if (!this.document.documentURIObject.schemeIs("http")) {
+ return;
+ }
+ // Ignore onion addresses
+ if (this.document.documentURIObject.host.endsWith(".onion")) {
+ return;
+ }
+
+ if (event.type == "copy" || event.type == "cut") {
+ this.contentWindow.navigator.clipboard.readText().then(clipText => {
+ const selection = clipText.trim();
+ if (looksLikeCryptoAddress(selection)) {
+ this.sendAsyncMessage("CryptoSafety:CopiedText", {
+ selection,
+ });
+ }
+ });
+ }
+ }
+ }
+}
diff --git a/browser/actors/CryptoSafetyParent.jsm b/browser/actors/CryptoSafetyParent.jsm
new file mode 100644
index 000000000000..bac151df5511
--- /dev/null
+++ b/browser/actors/CryptoSafetyParent.jsm
@@ -0,0 +1,142 @@
+/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
+/* Copyright (c) 2020, The Tor Project, Inc.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * 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/. */
+
+var EXPORTED_SYMBOLS = ["CryptoSafetyParent"];
+
+const { XPCOMUtils } = ChromeUtils.import(
+ "resource://gre/modules/XPCOMUtils.jsm"
+);
+
+XPCOMUtils.defineLazyModuleGetters(this, {
+ TorStrings: "resource:///modules/TorStrings.jsm",
+});
+
+const kPrefCryptoSafety = "security.cryptoSafety";
+
+XPCOMUtils.defineLazyPreferenceGetter(
+ this,
+ "isCryptoSafetyEnabled",
+ kPrefCryptoSafety,
+ true /* defaults to true */
+);
+
+class CryptoSafetyParent extends JSWindowActorParent {
+ getBrowser() {
+ return this.browsingContext.top.embedderElement;
+ }
+
+ receiveMessage(aMessage) {
+ if (isCryptoSafetyEnabled) {
+ if (aMessage.name == "CryptoSafety:CopiedText") {
+ showPopup(this.getBrowser(), aMessage.data.selection);
+ }
+ }
+ }
+}
+
+function trimAddress(cryptoAddr) {
+ if (cryptoAddr.length <= 32) {
+ return cryptoAddr;
+ }
+ return cryptoAddr.substring(0, 32) + "...";
+}
+
+function showPopup(aBrowser, cryptoAddr) {
+ const chromeDoc = aBrowser.ownerDocument;
+ if (chromeDoc) {
+ const win = chromeDoc.defaultView;
+ const cryptoSafetyPrompt = new CryptoSafetyPrompt(
+ aBrowser,
+ win,
+ cryptoAddr
+ );
+ cryptoSafetyPrompt.show();
+ }
+}
+
+class CryptoSafetyPrompt {
+ constructor(aBrowser, aWin, cryptoAddr) {
+ this._browser = aBrowser;
+ this._win = aWin;
+ this._cryptoAddr = cryptoAddr;
+ }
+
+ show() {
+ const primaryAction = {
+ label: TorStrings.cryptoSafetyPrompt.primaryAction,
+ accessKey: TorStrings.cryptoSafetyPrompt.primaryActionAccessKey,
+ callback: () => {
+ this._win.torbutton_new_circuit();
+ },
+ };
+
+ const secondaryAction = {
+ label: TorStrings.cryptoSafetyPrompt.secondaryAction,
+ accessKey: TorStrings.cryptoSafetyPrompt.secondaryActionAccessKey,
+ callback: () => {},
+ };
+
+ let _this = this;
+ const options = {
+ popupIconURL: "chrome://browser/skin/cert-error.svg",
+ eventCallback(aTopic) {
+ if (aTopic === "showing") {
+ _this._onPromptShowing();
+ }
+ },
+ };
+
+ const cryptoWarningText = TorStrings.cryptoSafetyPrompt.cryptoWarning.replace(
+ "%S",
+ trimAddress(this._cryptoAddr)
+ );
+
+ if (this._win.PopupNotifications) {
+ this._prompt = this._win.PopupNotifications.show(
+ this._browser,
+ "crypto-safety-warning",
+ cryptoWarningText,
+ null /* anchor ID */,
+ primaryAction,
+ [secondaryAction],
+ options
+ );
+ }
+ }
+
+ _onPromptShowing() {
+ let xulDoc = this._browser.ownerDocument;
+
+ let whatCanHeading = xulDoc.getElementById(
+ "crypto-safety-warning-notification-what-can-heading"
+ );
+ if (whatCanHeading) {
+ whatCanHeading.textContent = TorStrings.cryptoSafetyPrompt.whatCanHeading;
+ }
+
+ let whatCanBody = xulDoc.getElementById(
+ "crypto-safety-warning-notification-what-can-body"
+ );
+ if (whatCanBody) {
+ whatCanBody.textContent = TorStrings.cryptoSafetyPrompt.whatCanBody;
+ }
+
+ let learnMoreElem = xulDoc.getElementById(
+ "crypto-safety-warning-notification-learnmore"
+ );
+ if (learnMoreElem) {
+ learnMoreElem.setAttribute(
+ "value",
+ TorStrings.cryptoSafetyPrompt.learnMore
+ );
+ learnMoreElem.setAttribute(
+ "href",
+ TorStrings.cryptoSafetyPrompt.learnMoreURL
+ );
+ }
+ }
+}
diff --git a/browser/actors/moz.build b/browser/actors/moz.build
index e70f0f09fe3a..9eb5ca397060 100644
--- a/browser/actors/moz.build
+++ b/browser/actors/moz.build
@@ -50,6 +50,8 @@ FINAL_TARGET_FILES.actors += [
'ContentSearchParent.jsm',
'ContextMenuChild.jsm',
'ContextMenuParent.jsm',
+ 'CryptoSafetyChild.jsm',
+ 'CryptoSafetyParent.jsm',
'DOMFullscreenChild.jsm',
'DOMFullscreenParent.jsm',
'FormValidationChild.jsm',
diff --git a/browser/base/content/popup-notifications.inc b/browser/base/content/popup-notifications.inc
index 42e17e90c648..ff6f8cdeca80 100644
--- a/browser/base/content/popup-notifications.inc
+++ b/browser/base/content/popup-notifications.inc
@@ -114,3 +114,17 @@
</vbox>
</popupnotificationfooter>
</popupnotification>
+
+ <popupnotification id="crypto-safety-warning-notification" hidden="true">
+ <popupnotificationcontent orient="vertical">
+ <description id="crypto-safety-warning-notification-desc"/>
+ <html:div id="crypto-safety-warning-notification-what-can">
+ <html:strong id="crypto-safety-warning-notification-what-can-heading" />
+ <html:br/>
+ <html:span id="crypto-safety-warning-notification-what-can-body" />
+ </html:div>
+ <label id="crypto-safety-warning-notification-learnmore"
+ class="popup-notification-learnmore-link"
+ is="text-link"/>
+ </popupnotificationcontent>
+ </popupnotification>
diff --git a/browser/components/BrowserGlue.jsm b/browser/components/BrowserGlue.jsm
index 3750230a250b..5f708fca3d5c 100644
--- a/browser/components/BrowserGlue.jsm
+++ b/browser/components/BrowserGlue.jsm
@@ -297,6 +297,23 @@ let JSWINDOWACTORS = {
allFrames: true,
},
+ CryptoSafety: {
+ parent: {
+ moduleURI: "resource:///actors/CryptoSafetyParent.jsm",
+ },
+
+ child: {
+ moduleURI: "resource:///actors/CryptoSafetyChild.jsm",
+ group: "browsers",
+ events: {
+ copy: { mozSystemGroup: true },
+ cut: { mozSystemGroup: true },
+ },
+ },
+
+ allFrames: true,
+ },
+
DOMFullscreen: {
parent: {
moduleURI: "resource:///actors/DOMFullscreenParent.jsm",
diff --git a/browser/modules/TorStrings.jsm b/browser/modules/TorStrings.jsm
index e8a8d37ae373..1e08b168e4af 100644
--- a/browser/modules/TorStrings.jsm
+++ b/browser/modules/TorStrings.jsm
@@ -101,6 +101,54 @@ class TorPropertyStringBundle {
Security Level Strings
*/
var TorStrings = {
+ /*
+ CryptoSafetyPrompt Strings
+ */
+ cryptoSafetyPrompt: (function() {
+ let tsb = new TorPropertyStringBundle(
+ "chrome://torbutton/locale/torbutton.properties",
+ "cryptoSafetyPrompt."
+ );
+ let getString = function(key, fallback) {
+ return tsb.getString(key, fallback);
+ };
+
+ let retval = {
+ cryptoWarning: getString(
+ "cryptoWarning",
+ "A cryptocurrency address (%S) has been copied from an insecure website. It could have been modified."
+ ),
+ whatCanHeading: getString(
+ "whatCanHeading",
+ "What can you do about it?"
+ ),
+ whatCanBody: getString(
+ "whatCanBody",
+ "You can try reconnecting with a new circuit to establish a secure connection, or accept the risk and dismiss this warning."
+ ),
+ learnMore: getString("learnMore", "Learn more"),
+ learnMoreURL: `https://support.torproject.org/${getLocale()}/`,
+ primaryAction: getString(
+ "primaryAction",
+ "Reload Tab with a New Circuit"
+ ),
+ primaryActionAccessKey: getString(
+ "primaryActionAccessKey",
+ "R"
+ ),
+ secondaryAction: getString(
+ "secondaryAction",
+ "Dismiss Warning"
+ ),
+ secondaryActionAccessKey: getString(
+ "secondaryActionAccessKey",
+ "D"
+ ),
+ };
+
+ return retval;
+ })() /* CryptoSafetyPrompt Strings */,
+
/*
Tor Browser Security Level Strings
*/
diff --git a/browser/themes/shared/browser.inc.css b/browser/themes/shared/browser.inc.css
index 0113466e8e56..4ef27d880754 100644
--- a/browser/themes/shared/browser.inc.css
+++ b/browser/themes/shared/browser.inc.css
@@ -620,3 +620,8 @@ menupopup::part(drop-indicator) {
#sharing-warning-proceed-to-tab:hover {
background-color: rgb(0,62,170);
}
+
+#crypto-safety-warning-notification-what-can {
+ display: block;
+ margin: 5px;
+}
diff --git a/toolkit/content/license.html b/toolkit/content/license.html
index e44c31ec6d4e..90995236b41b 100644
--- a/toolkit/content/license.html
+++ b/toolkit/content/license.html
@@ -72,6 +72,7 @@
<li><a href="about:license#arm">ARM License</a></li>
<li><a href="about:license#babel">Babel License</a></li>
<li><a href="about:license#babylon">Babylon License</a></li>
+ <li><a href="about:license#bech32">Bech32 License</a></li>
<li><a href="about:license#bincode">bincode License</a></li>
<li><a href="about:license#bsd2clause">BSD 2-Clause License</a></li>
<li><a href="about:license#bsd3clause">BSD 3-Clause License</a></li>
@@ -2795,6 +2796,37 @@ furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+</pre>
+
+
+ <hr>
+
+ <h1><a id="bech32"></a>Bech32 License</h1>
+
+ <p>This license applies to the file
+ <code>toolkit/modules/Bech32Decode.jsm</code>.
+ </p>
+
+<pre>
+Copyright (c) 2017 Pieter Wuille
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
diff --git a/toolkit/modules/Bech32Decode.jsm b/toolkit/modules/Bech32Decode.jsm
new file mode 100644
index 000000000000..3a2bc7ae0a10
--- /dev/null
+++ b/toolkit/modules/Bech32Decode.jsm
@@ -0,0 +1,103 @@
+// Adapted from the reference implementation of Bech32
+// https://github.com/sipa/bech32
+
+// Copyright (c) 2017 Pieter Wuille
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+"use strict";
+
+/**
+ * JS module implementation of Bech32 decoding adapted from the reference
+ * implementation https://github.com/sipa/bech32.
+ */
+
+var EXPORTED_SYMBOLS = ["Bech32Decode"];
+
+var CHARSET = "qpzry9x8gf2tvdw0s3jn54khce6mua7l";
+var GENERATOR = [0x3b6a57b2, 0x26508e6d, 0x1ea119fa, 0x3d4233dd, 0x2a1462b3];
+
+function polymod(values) {
+ var chk = 1;
+ for (var p = 0; p < values.length; ++p) {
+ var top = chk >> 25;
+ chk = ((chk & 0x1ffffff) << 5) ^ values[p];
+ for (var i = 0; i < 5; ++i) {
+ if ((top >> i) & 1) {
+ chk ^= GENERATOR[i];
+ }
+ }
+ }
+ return chk;
+}
+
+function hrpExpand(hrp) {
+ var ret = [];
+ var p;
+ for (p = 0; p < hrp.length; ++p) {
+ ret.push(hrp.charCodeAt(p) >> 5);
+ }
+ ret.push(0);
+ for (p = 0; p < hrp.length; ++p) {
+ ret.push(hrp.charCodeAt(p) & 31);
+ }
+ return ret;
+}
+
+function verifyChecksum(hrp, data) {
+ return polymod(hrpExpand(hrp).concat(data)) === 1;
+}
+
+function Bech32Decode(bechString) {
+ var p;
+ var has_lower = false;
+ var has_upper = false;
+ for (p = 0; p < bechString.length; ++p) {
+ if (bechString.charCodeAt(p) < 33 || bechString.charCodeAt(p) > 126) {
+ return null;
+ }
+ if (bechString.charCodeAt(p) >= 97 && bechString.charCodeAt(p) <= 122) {
+ has_lower = true;
+ }
+ if (bechString.charCodeAt(p) >= 65 && bechString.charCodeAt(p) <= 90) {
+ has_upper = true;
+ }
+ }
+ if (has_lower && has_upper) {
+ return null;
+ }
+ bechString = bechString.toLowerCase();
+ var pos = bechString.lastIndexOf("1");
+ if (pos < 1 || pos + 7 > bechString.length || bechString.length > 90) {
+ return null;
+ }
+ var hrp = bechString.substring(0, pos);
+ var data = [];
+ for (p = pos + 1; p < bechString.length; ++p) {
+ var d = CHARSET.indexOf(bechString.charAt(p));
+ if (d === -1) {
+ return null;
+ }
+ data.push(d);
+ }
+ if (!verifyChecksum(hrp, data)) {
+ return null;
+ }
+ return { hrp: hrp, data: data.slice(0, data.length - 6) };
+}
diff --git a/toolkit/modules/moz.build b/toolkit/modules/moz.build
index e1f1eb5759c5..698d2773a7ed 100644
--- a/toolkit/modules/moz.build
+++ b/toolkit/modules/moz.build
@@ -160,6 +160,7 @@ EXTRA_JS_MODULES += [
'ActorManagerParent.jsm',
'AppMenuNotifications.jsm',
'AsyncPrefs.jsm',
+ 'Bech32Decode.jsm',
'BinarySearch.jsm',
'BrowserUtils.jsm',
'CanonicalJSON.jsm',
1
0
[tor-browser/tor-browser-78.12.0esr-11.0-1] Bug 40432: Prevent probing installed applications
by boklm@torproject.org 14 Jul '21
by boklm@torproject.org 14 Jul '21
14 Jul '21
commit 6174b3a8229d5011b568362c70b1d50b40d3f0a8
Author: Matthew Finkel <sysrqb(a)torproject.org>
Date: Mon May 17 18:09:09 2021 +0000
Bug 40432: Prevent probing installed applications
---
.../exthandler/nsExternalHelperAppService.cpp | 30 ++++++++++++++++++----
1 file changed, 25 insertions(+), 5 deletions(-)
diff --git a/uriloader/exthandler/nsExternalHelperAppService.cpp b/uriloader/exthandler/nsExternalHelperAppService.cpp
index 0dcc1d3ed6ab..7ff9c5b626a3 100644
--- a/uriloader/exthandler/nsExternalHelperAppService.cpp
+++ b/uriloader/exthandler/nsExternalHelperAppService.cpp
@@ -1002,8 +1002,33 @@ nsresult nsExternalHelperAppService::GetFileTokenForPath(
//////////////////////////////////////////////////////////////////////////////////////////////////////
// begin external protocol service default implementation...
//////////////////////////////////////////////////////////////////////////////////////////////////////
+
+static const char kExternalProtocolPrefPrefix[] =
+ "network.protocol-handler.external.";
+static const char kExternalProtocolDefaultPref[] =
+ "network.protocol-handler.external-default";
+
NS_IMETHODIMP nsExternalHelperAppService::ExternalProtocolHandlerExists(
const char* aProtocolScheme, bool* aHandlerExists) {
+
+ // Replicate the same check performed in LoadURI.
+ // Deny load if the prefs say to do so
+ nsAutoCString externalPref(kExternalProtocolPrefPrefix);
+ externalPref += aProtocolScheme;
+ bool allowLoad = false;
+ *aHandlerExists = false;
+ if (NS_FAILED(Preferences::GetBool(externalPref.get(), &allowLoad))) {
+ // no scheme-specific value, check the default
+ if (NS_FAILED(
+ Preferences::GetBool(kExternalProtocolDefaultPref, &allowLoad))) {
+ return NS_OK; // missing default pref
+ }
+ }
+
+ if (!allowLoad) {
+ return NS_OK; // explicitly denied
+ }
+
nsCOMPtr<nsIHandlerInfo> handlerInfo;
nsresult rv = GetProtocolHandlerInfo(nsDependentCString(aProtocolScheme),
getter_AddRefs(handlerInfo));
@@ -1046,11 +1071,6 @@ NS_IMETHODIMP nsExternalHelperAppService::IsExposedProtocol(
return NS_OK;
}
-static const char kExternalProtocolPrefPrefix[] =
- "network.protocol-handler.external.";
-static const char kExternalProtocolDefaultPref[] =
- "network.protocol-handler.external-default";
-
NS_IMETHODIMP
nsExternalHelperAppService::LoadURI(nsIURI* aURI,
nsIPrincipal* aTriggeringPrincipal,
1
0
[tor-browser/tor-browser-78.12.0esr-11.0-1] Adding issue template for bugs.
by boklm@torproject.org 14 Jul '21
by boklm@torproject.org 14 Jul '21
14 Jul '21
commit 8201e1f2c0875d4c2a852aee34914e508224988b
Author: Gaba <gaba(a)torproject.org>
Date: Mon Jun 28 11:44:16 2021 -0700
Adding issue template for bugs.
---
.gitlab/issue_templates/UXBug.md | 29 +++++++++++++++++++++++++++++
.gitlab/issue_templates/bug.md | 32 ++++++++++++++++++++++++++++++++
2 files changed, 61 insertions(+)
diff --git a/.gitlab/issue_templates/UXBug.md b/.gitlab/issue_templates/UXBug.md
new file mode 100644
index 000000000000..8e7cb2a5e163
--- /dev/null
+++ b/.gitlab/issue_templates/UXBug.md
@@ -0,0 +1,29 @@
+<!--
+* Use this issue template for reporting a new UX bug.
+-->
+
+### Summary
+**Summarize the bug encountered concisely.**
+
+
+### Steps to reproduce:
+**How one can reproduce the issue - this is very important.**
+
+1. Step 1
+2. Step 2
+3. ...
+
+### What is the current bug behavior?
+**What actually happens.**
+
+
+### What is the expected behavior?
+**What you want to see instead**
+
+
+
+## Relevant logs and/or screenshots
+**Do you have screenshots? Attach them to this ticket please.**
+
+/label ~tor-ux ~needs-investigation ~bug
+/assign @nah
diff --git a/.gitlab/issue_templates/bug.md b/.gitlab/issue_templates/bug.md
new file mode 100644
index 000000000000..6ce85a4864be
--- /dev/null
+++ b/.gitlab/issue_templates/bug.md
@@ -0,0 +1,32 @@
+<!--
+* Use this issue template for reporting a new bug.
+-->
+
+### Summary
+**Summarize the bug encountered concisely.**
+
+
+### Steps to reproduce:
+**How one can reproduce the issue - this is very important.**
+
+1. Step 1
+2. Step 2
+3. ...
+
+### What is the current bug behavior?
+**What actually happens.**
+
+
+### What is the expected behavior?
+**What you want to see instead**
+
+
+
+### Environment
+**Which operating system are you using? For example: Debian GNU/Linux 10.1, Windows 10, Ubuntu Xenial, FreeBSD 12.2, etc.**
+**Which installation method did you use? Distribution package (apt, pkg, homebrew), from source tarball, from Git, etc.**
+
+### Relevant logs and/or screenshots
+
+
+/label ~bug
1
0
[tor-browser/tor-browser-78.12.0esr-11.0-1] Bug 1650281 - P1: Widen `gCombinedSizes` once the buffers grow r=gerald
by boklm@torproject.org 14 Jul '21
by boklm@torproject.org 14 Jul '21
14 Jul '21
commit da7434fa9e375035ef31e12ea0a3c0ffcc36a970
Author: Chun-Min Chang <chun.m.chang(a)gmail.com>
Date: Tue Jul 21 23:38:57 2020 +0000
Bug 1650281 - P1: Widen `gCombinedSizes` once the buffers grow r=gerald
The `gCombinedSizes` need to be enlarged once the inner buffer within
`MemoryBlockCache` grows. Otherwise, when the `MemoryBlockCache` is
released, subtracting the buffer-size of the `MemoryBlockCache` from
`gCombinedSizes` lead to a underflow.
Differential Revision: https://phabricator.services.mozilla.com/D84273
---
dom/media/MemoryBlockCache.cpp | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/dom/media/MemoryBlockCache.cpp b/dom/media/MemoryBlockCache.cpp
index 2d31119dca0a..bf073e6769d0 100644
--- a/dom/media/MemoryBlockCache.cpp
+++ b/dom/media/MemoryBlockCache.cpp
@@ -114,6 +114,10 @@ bool MemoryBlockCache::EnsureBufferCanContain(size_t aContentLength) {
// possibly bypass some future growths that would fit in this new capacity.
mBuffer.SetLength(capacity);
}
+ const size_t newSizes = gCombinedSizes += (extra + extraCapacity);
+ LOG("EnsureBufferCanContain(%zu) - buffer size %zu + requested %zu + bonus "
+ "%zu = %zu; combined sizes %zu",
+ aContentLength, initialLength, extra, extraCapacity, capacity, newSizes);
mHasGrown = true;
return true;
}
1
0
[tor-browser/tor-browser-78.12.0esr-11.0-1] Bug 40002: Remove about:pioneer
by boklm@torproject.org 14 Jul '21
by boklm@torproject.org 14 Jul '21
14 Jul '21
commit 53c3d8aa1166ccea0f9e88f3d2658d2d28de2eb3
Author: Kathy Brade <brade(a)pearlcrescent.com>
Date: Fri Aug 14 09:06:33 2020 -0400
Bug 40002: Remove about:pioneer
Firefox Pioneer is an opt-in program in which people volunteer to
participate in studies that collect detailed, sensitive data about
how they use their browser.
---
browser/components/about/AboutRedirector.cpp | 2 --
browser/components/about/components.conf | 1 -
2 files changed, 3 deletions(-)
diff --git a/browser/components/about/AboutRedirector.cpp b/browser/components/about/AboutRedirector.cpp
index 544e21782729..e7c377d655e7 100644
--- a/browser/components/about/AboutRedirector.cpp
+++ b/browser/components/about/AboutRedirector.cpp
@@ -114,8 +114,6 @@ static const RedirEntry kRedirMap[] = {
nsIAboutModule::URI_MUST_LOAD_IN_CHILD |
nsIAboutModule::URI_SAFE_FOR_UNTRUSTED_CONTENT |
nsIAboutModule::ALLOW_SCRIPT | nsIAboutModule::HIDE_FROM_ABOUTABOUT},
- {"pioneer", "chrome://browser/content/pioneer.html",
- nsIAboutModule::ALLOW_SCRIPT | nsIAboutModule::HIDE_FROM_ABOUTABOUT},
#ifdef TOR_BROWSER_UPDATE
{"tbupdate", "chrome://browser/content/abouttbupdate/aboutTBUpdate.xhtml",
nsIAboutModule::URI_SAFE_FOR_UNTRUSTED_CONTENT |
diff --git a/browser/components/about/components.conf b/browser/components/about/components.conf
index d78de142e2e4..8e04467c05da 100644
--- a/browser/components/about/components.conf
+++ b/browser/components/about/components.conf
@@ -14,7 +14,6 @@ pages = [
'logins',
'newinstall',
'newtab',
- 'pioneer',
'pocket-saved',
'pocket-signup',
'policies',
1
0
[tor-browser/tor-browser-78.12.0esr-11.0-1] Bug 1658881 - When failing to create a channel and an image request, make sure to set the image blocking status appropriately. r=tnikkel
by boklm@torproject.org 14 Jul '21
by boklm@torproject.org 14 Jul '21
14 Jul '21
commit 36fa1d38f7e466e5843f882654844e5ced85ba00
Author: Emilio Cobos Álvarez <emilio(a)crisal.io>
Date: Wed Sep 9 22:58:29 2020 +0000
Bug 1658881 - When failing to create a channel and an image request, make sure to set the image blocking status appropriately. r=tnikkel
This is the same status as we do for known no-data protocols here:
https://searchfox.org/mozilla-central/rev/ac142717cc067d875e83e4b1316f004f6…
This ensures we treat these two cases the same.
Differential Revision: https://phabricator.services.mozilla.com/D89382
---
dom/base/nsImageLoadingContent.cpp | 7 ++++++-
layout/reftests/image/reftest.list | 1 +
layout/reftests/image/unknown-protocol-ref.html | 1 +
layout/reftests/image/unknown-protocol.html | 1 +
4 files changed, 9 insertions(+), 1 deletion(-)
diff --git a/dom/base/nsImageLoadingContent.cpp b/dom/base/nsImageLoadingContent.cpp
index 23b1fd791c1f..85de63bef02d 100644
--- a/dom/base/nsImageLoadingContent.cpp
+++ b/dom/base/nsImageLoadingContent.cpp
@@ -1207,7 +1207,12 @@ nsresult nsImageLoadingContent::LoadImage(nsIURI* aNewURI, bool aForce,
MOZ_ASSERT(!req, "Shouldn't have non-null request here");
// If we don't have a current URI, we might as well store this URI so people
// know what we tried (and failed) to load.
- if (!mCurrentRequest) mCurrentURI = aNewURI;
+ if (!mCurrentRequest) {
+ mCurrentURI = aNewURI;
+ if (mImageBlockingStatus == nsIContentPolicy::ACCEPT) {
+ mImageBlockingStatus = nsIContentPolicy::REJECT_REQUEST;
+ }
+ }
FireEvent(NS_LITERAL_STRING("error"));
FireEvent(NS_LITERAL_STRING("loadend"));
diff --git a/layout/reftests/image/reftest.list b/layout/reftests/image/reftest.list
index a8a91c13ed3a..3c561fe3a7c8 100644
--- a/layout/reftests/image/reftest.list
+++ b/layout/reftests/image/reftest.list
@@ -69,3 +69,4 @@ random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == image-srcset-basic-selec
pref(dom.image-lazy-loading.enabled,true) == moz-broken-matching-lazy-load.html moz-broken-matching-1-ref.html
== img-invalidation-local-transform-1.html img-invalidation-local-transform-1-ref.html
+== unknown-protocol.html unknown-protocol-ref.html
diff --git a/layout/reftests/image/unknown-protocol-ref.html b/layout/reftests/image/unknown-protocol-ref.html
new file mode 100644
index 000000000000..b5bb326eef57
--- /dev/null
+++ b/layout/reftests/image/unknown-protocol-ref.html
@@ -0,0 +1 @@
+<img src="mailto://foo">
diff --git a/layout/reftests/image/unknown-protocol.html b/layout/reftests/image/unknown-protocol.html
new file mode 100644
index 000000000000..ef06881b7bcb
--- /dev/null
+++ b/layout/reftests/image/unknown-protocol.html
@@ -0,0 +1 @@
+<img src="foobar://baz">
1
0
[tor-browser/tor-browser-78.12.0esr-11.0-1] Bug 40416: Add v2 Onion deprecation warnings
by boklm@torproject.org 14 Jul '21
by boklm@torproject.org 14 Jul '21
14 Jul '21
commit 1eaade2adee6e68de1952ed7a6bac4f84805b3aa
Author: Richard Pospesel <richard(a)torproject.org>
Date: Fri May 21 22:18:23 2021 +0200
Bug 40416: Add v2 Onion deprecation warnings
- adds new v2 deprecated warning page (js and styling) that piggy-backs
off of the existing added onion service errors
- updates identity-icon to onionWarning.svg when visiting a v2 onion site adds
warning tooltip; this warning supersedes all other identity states (including
mixed-content error)
- we determine whether to show the warning page in nsDocShell::DoURILoad()
- a new synchonous IPC method is added to ContentChild/ContentParent to determine
if the session has loaded the warning page already; worst case scenario, each
child process will need to wait on this method to return only once when visiting
a v2 onion; nothing is permanently cached with regards to this change
- an exception for the new sync method is added to sync-messages.ini (generally,
in practice adding new blocking methods is probably bad, but the minimial
overhead and frequency this method is called is worth the simpler code)
---
browser/base/content/aboutNetError.xhtml | 3 ++
browser/base/content/browser-siteIdentity.js | 12 +++++
browser/base/jar.mn | 2 +-
.../content/netError/onionNetError.js | 6 +++
.../content/netError/v2Deprecated.css | 25 +++++++++
.../onionservices/content/netError/v2Deprecated.js | 50 ++++++++++++++++++
browser/components/onionservices/jar.mn | 8 ++-
browser/modules/TorStrings.jsm | 8 +++
.../shared/identity-block/identity-block.inc.css | 3 +-
browser/themes/shared/onionPattern.inc.xhtml | 4 +-
docshell/base/nsDocShell.cpp | 61 ++++++++++++++++++++++
dom/ipc/ContentParent.cpp | 11 ++++
dom/ipc/ContentParent.h | 2 +
dom/ipc/PContent.ipdl | 3 ++
ipc/ipdl/sync-messages.ini | 3 ++
js/xpconnect/src/xpc.msg | 1 +
xpcom/base/ErrorList.py | 2 +
17 files changed, 200 insertions(+), 4 deletions(-)
diff --git a/browser/base/content/aboutNetError.xhtml b/browser/base/content/aboutNetError.xhtml
index 957b6f15a0be..4572eb2024f1 100644
--- a/browser/base/content/aboutNetError.xhtml
+++ b/browser/base/content/aboutNetError.xhtml
@@ -207,7 +207,10 @@
</div>
</div>
</div>
+<!-- The onion pattern is disabled by default unless the onionPattern.css is also included; we include onionPattern.css programmatically in the v2Deprecation error page, so the onion pattern will not be visible in all error pages -->
+#include ../../themes/shared/onionPattern.inc.xhtml
</body>
+ <script src="chrome://browser/content/onionservices/netError/v2Deprecated.js"/>
<script src="chrome://browser/content/onionservices/netError/onionNetError.js"/>
<script src="chrome://browser/content/aboutNetError.js"/>
</html>
diff --git a/browser/base/content/browser-siteIdentity.js b/browser/base/content/browser-siteIdentity.js
index 2a3431172886..27fee74cba5b 100644
--- a/browser/base/content/browser-siteIdentity.js
+++ b/browser/base/content/browser-siteIdentity.js
@@ -135,6 +135,15 @@ var gIdentityHandler = {
return this._uriHasHost ? this._uri.host.toLowerCase().endsWith(".onion") : false;
},
+ get _uriIsDeprecatedOnionHost() {
+ const hostIsV2Onion = function(host) {
+ // matches on v2 onion domains with any number of subdomains
+ const pattern = /^(.*\.)*[a-z2-7]{16}\.onion/i;
+ return pattern.test(host);
+ };
+
+ return this._uriHasHost ? hostIsV2Onion(this._uri.host) : false;
+ },
// smart getters
get _identityPopup() {
delete this._identityPopup;
@@ -685,6 +694,9 @@ var gIdentityHandler = {
"identity.extension.label",
[extensionName]
);
+ } else if (this._uriIsDeprecatedOnionHost) {
+ this._identityBox.className = "onionServiceDeprecated";
+ tooltip = TorStrings.onionServices.v2Deprecated.tooltip;
} else if (this._uriHasHost && this._isSecureConnection && this._secInfo) {
// This is a secure connection.
// _isSecureConnection implicitly includes onion services, which may not have an SSL certificate
diff --git a/browser/base/jar.mn b/browser/base/jar.mn
index df65349796b5..21b07ad9511b 100644
--- a/browser/base/jar.mn
+++ b/browser/base/jar.mn
@@ -22,7 +22,7 @@ browser.jar:
content/browser/logos/send.svg (content/logos/send.svg)
content/browser/logos/tracking-protection.svg (content/logos/tracking-protection.svg)
content/browser/logos/tracking-protection-dark-theme.svg (content/logos/tracking-protection-dark-theme.svg)
- content/browser/aboutNetError.xhtml (content/aboutNetError.xhtml)
+* content/browser/aboutNetError.xhtml (content/aboutNetError.xhtml)
content/browser/aboutNetError.js (content/aboutNetError.js)
content/browser/aboutRobots-icon.png (content/aboutRobots-icon.png)
content/browser/aboutFrameCrashed.html (content/aboutFrameCrashed.html)
diff --git a/browser/components/onionservices/content/netError/onionNetError.js b/browser/components/onionservices/content/netError/onionNetError.js
index 8fabb3f38eb7..254e50bab4a3 100644
--- a/browser/components/onionservices/content/netError/onionNetError.js
+++ b/browser/components/onionservices/content/netError/onionNetError.js
@@ -38,6 +38,12 @@ var OnionServicesAboutNetError = {
const errPrefix = "onionServices.";
const errName = err.substring(errPrefix.length);
+ // tor-browser#40416 - remove this page and updated onionNetErrors with new error once v2 no longer works at all
+ if (errName === "v2Deprecated") {
+ V2DeprecatedAboutNetError.initPage(aDoc);
+ return;
+ }
+
this._strings = RPMGetTorStrings();
const stringsObj = this._strings[errName];
diff --git a/browser/components/onionservices/content/netError/v2Deprecated.css b/browser/components/onionservices/content/netError/v2Deprecated.css
new file mode 100644
index 000000000000..890468d09761
--- /dev/null
+++ b/browser/components/onionservices/content/netError/v2Deprecated.css
@@ -0,0 +1,25 @@
+%include ../../../../themes/shared/onionPattern.css
+
+:root {
+ --onion-opacity: 1;
+ --onion-color: var(--card-outline-color);
+ --onion-radius: 50px;
+}
+
+body {
+ border: 1.5em solid #FED916;
+ justify-content: space-between;
+}
+
+div.title {
+ background-image: url("chrome://browser/skin/onion-warning.svg");
+}
+
+div#errorPageContainer {
+ padding-top: 20vh;
+ width: 66%;
+}
+
+div#learnMoreContainer {
+ display: block;
+}
\ No newline at end of file
diff --git a/browser/components/onionservices/content/netError/v2Deprecated.js b/browser/components/onionservices/content/netError/v2Deprecated.js
new file mode 100644
index 000000000000..195bc187791c
--- /dev/null
+++ b/browser/components/onionservices/content/netError/v2Deprecated.js
@@ -0,0 +1,50 @@
+// Copyright (c) 2021, The Tor Project, Inc.
+
+"use strict";
+
+/* eslint-env mozilla/frame-script */
+
+var V2DeprecatedAboutNetError = {
+
+ _selector: {
+ header: ".title-text",
+ longDesc: "#errorLongDesc",
+ learnMoreLink: "#learnMoreLink",
+ contentContainer: "#errorLongContent",
+ tryAgainButton: "div#netErrorButtonContainer button.try-again",
+ },
+
+ initPage(aDoc) {
+ this._insertStylesheet(aDoc);
+ this._populateStrings(aDoc);
+ },
+
+ _populateStrings(aDoc) {
+ // populate strings
+ const TorStrings = RPMGetTorStrings();
+
+ aDoc.title = TorStrings.v2Deprecated.pageTitle;
+
+ let headerElem = aDoc.querySelector(this._selector.header);
+ headerElem.textContent = TorStrings.v2Deprecated.header;
+
+ let longDescriptionElem = aDoc.querySelector(this._selector.longDesc);
+ longDescriptionElem.textContent = TorStrings.v2Deprecated.longDescription;
+
+ let learnMoreElem = aDoc.querySelector(this._selector.learnMoreLink);
+ learnMoreElem.setAttribute("href", TorStrings.v2Deprecated.learnMoreURL);
+
+ let tryAgainElem = aDoc.querySelector(this._selector.tryAgainButton);
+ tryAgainElem.textContent = TorStrings.v2Deprecated.tryAgain;
+ },
+
+ _insertStylesheet(aDoc) {
+ const url =
+ "chrome://browser/content/onionservices/netError/v2Deprecated.css";
+ let linkElem = aDoc.createElement("link");
+ linkElem.rel = "stylesheet";
+ linkElem.href = url;
+ linkElem.type = "text/css";
+ aDoc.head.appendChild(linkElem);
+ },
+};
diff --git a/browser/components/onionservices/jar.mn b/browser/components/onionservices/jar.mn
index f45b16dc5d29..73258bd9c501 100644
--- a/browser/components/onionservices/jar.mn
+++ b/browser/components/onionservices/jar.mn
@@ -3,7 +3,13 @@ browser.jar:
content/browser/onionservices/authPreferences.js (content/authPreferences.js)
content/browser/onionservices/authPrompt.js (content/authPrompt.js)
content/browser/onionservices/authUtil.jsm (content/authUtil.jsm)
- content/browser/onionservices/netError/ (content/netError/*)
+ content/browser/onionservices/netError/browser.svg (content/netError/browser.svg)
+ content/browser/onionservices/netError/network.svg (content/netError/network.svg)
+ content/browser/onionservices/netError/onionNetError.css (content/netError/onionNetError.css)
+ content/browser/onionservices/netError/onionNetError.js (content/netError/onionNetError.js)
+ content/browser/onionservices/netError/onionsite.svg (content/netError/onionsite.svg)
+* content/browser/onionservices/netError/v2Deprecated.css (content/netError/v2Deprecated.css)
+ content/browser/onionservices/netError/v2Deprecated.js (content/netError/v2Deprecated.js)
content/browser/onionservices/onionservices.css (content/onionservices.css)
content/browser/onionservices/savedKeysDialog.js (content/savedKeysDialog.js)
content/browser/onionservices/savedKeysDialog.xhtml (content/savedKeysDialog.xhtml)
diff --git a/browser/modules/TorStrings.jsm b/browser/modules/TorStrings.jsm
index c086d0fe3117..6eeb2ea06a04 100644
--- a/browser/modules/TorStrings.jsm
+++ b/browser/modules/TorStrings.jsm
@@ -502,6 +502,14 @@ var TorStrings = {
header: getString("introTimedOut.header", "Onionsite Circuit Creation Timed Out"),
longDescription: getString("introTimedOut.longDescription", kLongDescFallback),
},
+ v2Deprecated: { // Deprecation page for v2 Onions
+ pageTitle: getString("v2Deprecated.pageTitle", "V2 Onion Site Deprecation Warning"),
+ header: getString("v2Deprecated.header", "Version 2 Onion Sites will be deprecated soon"),
+ longDescription: getString("v2Deprecated.longDescription", "Tor is ending its support for version 2 onion services beginning in July 2021, and this onion site will no longer be reachable at this address. If you are the site administrator, upgrade to a version 3 onion service soon."),
+ learnMoreURL: `https://support.torproject.org/${getLocale()}/onionservices/#v2-deprecation`,
+ tryAgain: getString("v2Deprecated.tryAgain", "Got it"),
+ tooltip: getString("v2Deprecated.tooltip", "This onion site will not be reachable soon"),
+ },
authPrompt: {
description:
getString("authPrompt.description2", "%S is requesting that you authenticate."),
diff --git a/browser/themes/shared/identity-block/identity-block.inc.css b/browser/themes/shared/identity-block/identity-block.inc.css
index 011fb9f3081c..936ab00d2080 100644
--- a/browser/themes/shared/identity-block/identity-block.inc.css
+++ b/browser/themes/shared/identity-block/identity-block.inc.css
@@ -181,7 +181,8 @@ toolbar[brighttext] #identity-box[pageproxystate="valid"].chromeUI > #identity-i
#identity-box[pageproxystate="valid"].onionMixedDisplayContent > #identity-icon,
#identity-box[pageproxystate="valid"].onionMixedDisplayContentLoadedActiveBlocked > #identity-icon,
-#identity-box[pageproxystate="valid"].onionCertUserOverridden > #identity-icon {
+#identity-box[pageproxystate="valid"].onionCertUserOverridden > #identity-icon,
+#identity-box[pageproxystate="valid"].onionServiceDeprecated > #identity-icon {
list-style-image: url(chrome://browser/skin/onion-warning.svg);
visibility: visible;
}
diff --git a/browser/themes/shared/onionPattern.inc.xhtml b/browser/themes/shared/onionPattern.inc.xhtml
index 6bbde93684a2..0b6b8b072f9a 100644
--- a/browser/themes/shared/onionPattern.inc.xhtml
+++ b/browser/themes/shared/onionPattern.inc.xhtml
@@ -9,9 +9,11 @@
- most browser windows, typically the two rows of onions will fill the
- bottom of the page. On really wide pages, the onions are centered at
- the bottom of the page.
+ - The root onion-pattern-container div is hidden by default, and can be
+ - enabled by including onionPattern.css
-->
-<div class="onion-pattern-container">
+<div class="onion-pattern-container" style="display: none">
<!-- for some reason, these two elements are focusable, seems related to
- flex css somehow; disable their tabindex to fix
-->
diff --git a/docshell/base/nsDocShell.cpp b/docshell/base/nsDocShell.cpp
index bf9639c82612..0f315f2f87b4 100644
--- a/docshell/base/nsDocShell.cpp
+++ b/docshell/base/nsDocShell.cpp
@@ -7,6 +7,7 @@
#include "nsDocShell.h"
#include <algorithm>
+#include <regex>
#ifdef XP_WIN
# include <process.h>
@@ -3645,6 +3646,9 @@ nsDocShell::DisplayLoadError(nsresult aError, nsIURI* aURI,
case NS_ERROR_TOR_ONION_SVC_INTRO_TIMEDOUT:
error = "onionServices.introTimedOut";
break;
+ case NS_ERROR_TOR_ONION_SVC_V2_DEPRECATED:
+ error = "onionServices.v2Deprecated";
+ break;
default:
break;
}
@@ -9596,6 +9600,63 @@ nsresult nsDocShell::DoURILoad(nsDocShellLoadState* aLoadState,
return NS_OK;
}
+ // tor-browser#40416
+ // we only ever want to show the warning page once per session
+ const auto shouldShouldShowV2DeprecationPage = []() -> bool {
+ bool retval = false;
+ if (XRE_IsContentProcess()) {
+ auto* cc = ContentChild::GetSingleton();
+ cc->SendShouldShowV2DeprecationPage(&retval);
+ }
+ return retval;
+ };
+
+ const auto uriIsV2Onion = [](nsIURI* uri) -> bool {
+ if (uri) {
+ nsAutoCString hostString;
+ uri->GetHost(hostString);
+
+ const std::string_view host(hostString.BeginReading(), hostString.Length());
+
+ // matches v2 onions with any number of subdomains
+ const static std::regex v2OnionPattern{
+ "^(.*\\.)*[a-z2-7]{16}\\.onion",
+ std::regex::icase | std::regex::optimize
+ };
+
+ // see if the uri refers to v2 onion host
+ return std::regex_match(
+ host.begin(),
+ host.end(),
+ v2OnionPattern);
+ }
+ return false;
+ };
+
+ // only dip in here if this process thinks onion warning page has not been shown
+ static bool v2DeprecationPageShown = false;
+ if (!v2DeprecationPageShown) {
+ // now only advance if the URI we are dealing with
+ // is a v2 onion address
+ auto uri = aLoadState->URI();
+ if (uriIsV2Onion(uri)) {
+ // Ok, so we are dealing with a v2 onion, now make
+ // sure the v2 deprecation page has not been shown in
+ // in another content process
+ //
+ // This is a synchrynous call, so we are blocking until
+ // we hear back from from the parent process. Each child
+ // process will need to perform this wait at most once,
+ // since we are locally caching in v2DeprecationPageShown.
+ v2DeprecationPageShown = true;
+ if (shouldShouldShowV2DeprecationPage()) {
+ DisplayLoadError(NS_ERROR_TOR_ONION_SVC_V2_DEPRECATED, uri, nullptr, nullptr);
+ return NS_ERROR_LOAD_SHOWED_ERRORPAGE;
+ }
+ }
+ }
+
+
nsCOMPtr<nsIURILoader> uriLoader = components::URILoader::Service();
if (NS_WARN_IF(!uriLoader)) {
return NS_ERROR_UNEXPECTED;
diff --git a/dom/ipc/ContentParent.cpp b/dom/ipc/ContentParent.cpp
index 4269016ec5d5..9c1c1fddf9e9 100644
--- a/dom/ipc/ContentParent.cpp
+++ b/dom/ipc/ContentParent.cpp
@@ -6515,6 +6515,17 @@ NS_IMETHODIMP ContentParent::GetActor(const nsACString& aName,
return NS_OK;
}
+mozilla::ipc::IPCResult ContentParent::RecvShouldShowV2DeprecationPage(bool* showPage) {
+ static bool v2DeprecationPageShown = false;
+ if (v2DeprecationPageShown) {
+ *showPage = false;
+ } else {
+ *showPage = true;
+ v2DeprecationPageShown = true;
+ }
+ return IPC_OK();
+}
+
} // namespace dom
} // namespace mozilla
diff --git a/dom/ipc/ContentParent.h b/dom/ipc/ContentParent.h
index 4f10832d8e23..83f9caa1dc6c 100644
--- a/dom/ipc/ContentParent.h
+++ b/dom/ipc/ContentParent.h
@@ -1280,6 +1280,8 @@ class ContentParent final
const MaybeDiscarded<BrowsingContext>& aContext, int32_t aOffset,
HistoryGoResolver&& aResolveRequestedIndex);
+ mozilla::ipc::IPCResult RecvShouldShowV2DeprecationPage(bool* showPage);
+
// Notify the ContentChild to enable the input event prioritization when
// initializing.
void MaybeEnableRemoteInputEventQueue();
diff --git a/dom/ipc/PContent.ipdl b/dom/ipc/PContent.ipdl
index c4dd750e47a4..09d053c69738 100644
--- a/dom/ipc/PContent.ipdl
+++ b/dom/ipc/PContent.ipdl
@@ -1678,6 +1678,9 @@ child:
// WindowContext is managed using the PWindowGlobal actor's lifecycle.
async CreateWindowContext(WindowContextInitializer aInit);
async DiscardWindowContext(uint64_t aContextId) returns (bool unused);
+
+parent:
+ sync ShouldShowV2DeprecationPage() returns (bool showPage);
};
}
diff --git a/ipc/ipdl/sync-messages.ini b/ipc/ipdl/sync-messages.ini
index 88ad49d169e8..df2acb04c750 100644
--- a/ipc/ipdl/sync-messages.ini
+++ b/ipc/ipdl/sync-messages.ini
@@ -1040,6 +1040,9 @@ description = Initialization of WebGL contexts is synchronous by spec.
description = Synchronous RPC to allow WebGL to run graphics commands in compositor process and return results to be used in JS return values.
[PSocketProcess::GetTLSClientCert]
description = Synchronously get client certificate and key from parent process. Once bug 696976 has been fixed, this can be removed.
+[PContent::ShouldShowV2DeprecationPage]
+description = Synchronously determine whether a client process has already displayed the v2 onion deprecation warning page
+
#############################################################
# AVOID ADDING NEW MESSAGES TO THIS FILE #
diff --git a/js/xpconnect/src/xpc.msg b/js/xpconnect/src/xpc.msg
index 31e5e75ba35c..7c8cc9ef181c 100644
--- a/js/xpconnect/src/xpc.msg
+++ b/js/xpconnect/src/xpc.msg
@@ -262,6 +262,7 @@ XPC_MSG_DEF(NS_ERROR_TOR_ONION_SVC_MISSING_CLIENT_AUTH, "Tor onion service missi
XPC_MSG_DEF(NS_ERROR_TOR_ONION_SVC_BAD_CLIENT_AUTH , "Tor onion service wrong client authorization")
XPC_MSG_DEF(NS_ERROR_TOR_ONION_SVC_BAD_ADDRESS , "Tor onion service bad address")
XPC_MSG_DEF(NS_ERROR_TOR_ONION_SVC_INTRO_TIMEDOUT , "Tor onion service introduction timed out")
+XPC_MSG_DEF(NS_ERROR_TOR_ONION_SVC_V2_DEPRECATED , "Tor v2 onion services are deprecated")
/* Profile manager error codes */
XPC_MSG_DEF(NS_ERROR_DATABASE_CHANGED , "Flushing the profiles to disk would have overwritten changes made elsewhere.")
diff --git a/xpcom/base/ErrorList.py b/xpcom/base/ErrorList.py
index 5f35cf7771f9..6bcd65f9bca9 100755
--- a/xpcom/base/ErrorList.py
+++ b/xpcom/base/ErrorList.py
@@ -1200,6 +1200,8 @@ with modules["TOR"]:
errors["NS_ERROR_TOR_ONION_SVC_BAD_ADDRESS"] = FAILURE(7)
# Tor onion service introduction timed out.
errors["NS_ERROR_TOR_ONION_SVC_INTRO_TIMEDOUT"] = FAILURE(8)
+ # Tor v2 onion services are deprecated
+ errors["NS_ERROR_TOR_ONION_SVC_V2_DEPRECATED"] = FAILURE(9)
# =======================================================================
# 51: NS_ERROR_MODULE_GENERAL
1
0
[tor-browser/tor-browser-78.12.0esr-11.0-1] Bug 3547: Block all plugins.
by boklm@torproject.org 14 Jul '21
by boklm@torproject.org 14 Jul '21
14 Jul '21
commit 0763f589e1da827013606d03f3c0ffda9c70ab52
Author: Mike Perry <mikeperry-git(a)torproject.org>
Date: Tue Dec 4 16:03:13 2012 -0800
Bug 3547: Block all plugins.
We cannot use the @mozilla.org/extensions/blocklist;1 service, because we
actually want to stop plugins from ever entering the browser's process space
and/or executing code (for example, AV plugins that collect statistics/analyse
urls, magical toolbars that phone home or "help" the user, skype buttons that
ruin our day, and censorship filters). Hence we rolled our own.
See https://trac.torproject.org/projects/tor/ticket/3547#comment:6 for musings
on a better way. Until then, it is delta-darwinism for us.
---
dom/plugins/base/PluginFinder.cpp | 3 +++
1 file changed, 3 insertions(+)
diff --git a/dom/plugins/base/PluginFinder.cpp b/dom/plugins/base/PluginFinder.cpp
index 4e1c1fd53698..cace7d4ef6ba 100644
--- a/dom/plugins/base/PluginFinder.cpp
+++ b/dom/plugins/base/PluginFinder.cpp
@@ -480,6 +480,9 @@ nsresult PluginFinder::ScanPluginsDirectory(nsIFile* pluginsDir,
*aPluginsChanged = false;
+ // Block all plugins
+ return NS_OK;
+
#ifdef PLUGIN_LOGGING
nsAutoCString dirPath;
pluginsDir->GetNativePath(dirPath);
1
0
[tor-browser/tor-browser-78.12.0esr-11.0-1] Bug 10760: Integrate TorButton to TorBrowser core
by boklm@torproject.org 14 Jul '21
by boklm@torproject.org 14 Jul '21
14 Jul '21
commit 47642982f7dc760a102f348009762cceb32ecd51
Author: Alex Catarineu <acat(a)torproject.org>
Date: Wed Feb 19 23:05:08 2020 +0100
Bug 10760: Integrate TorButton to TorBrowser core
Because of the non-restartless nature of Torbutton, it required
a two-stage installation process. On mobile, it was a problem,
because it was not loading when the user opened the browser for
the first time.
Moving it to tor-browser and making it a system extension allows it
to load when the user opens the browser for first time.
Additionally, this patch also fixes Bug 27611.
Bug 26321: New Circuit and New Identity menu items
Bug 14392: Make about:tor behave like other initial pages.
Bug 25013: Add torbutton as a tor-browser submodule
---
.gitmodules | 3 ++
browser/base/content/aboutDialog.xhtml | 38 +++++++++++------
browser/base/content/browser-doctype.inc | 6 +++
browser/base/content/browser-menubar.inc | 49 ++++++++++++++++------
browser/base/content/browser-sets.inc | 2 +
browser/base/content/browser.js | 1 +
browser/base/content/browser.xhtml | 9 ++++
.../controlcenter/content/identityPanel.inc.xhtml | 17 ++++++++
.../customizableui/content/panelUI.inc.xhtml | 17 +++++++-
browser/installer/package-manifest.in | 2 +
docshell/base/nsAboutRedirector.cpp | 6 ++-
docshell/build/components.conf | 1 +
mobile/android/installer/package-manifest.in | 4 ++
toolkit/moz.build | 1 +
.../mozapps/extensions/internal/XPIProvider.jsm | 9 ++++
toolkit/torproject/torbutton | 1 +
.../lib/environments/browser-window.js | 6 ++-
17 files changed, 142 insertions(+), 30 deletions(-)
diff --git a/.gitmodules b/.gitmodules
new file mode 100644
index 000000000000..2f03bd8e22df
--- /dev/null
+++ b/.gitmodules
@@ -0,0 +1,3 @@
+[submodule "toolkit/torproject/torbutton"]
+ path = toolkit/torproject/torbutton
+ url = https://git.torproject.org/torbutton.git
diff --git a/browser/base/content/aboutDialog.xhtml b/browser/base/content/aboutDialog.xhtml
index 69cbf846bbef..5274cbc02831 100644
--- a/browser/base/content/aboutDialog.xhtml
+++ b/browser/base/content/aboutDialog.xhtml
@@ -7,11 +7,11 @@
<?xml-stylesheet href="chrome://global/skin/global.css" type="text/css"?>
<?xml-stylesheet href="chrome://browser/content/aboutDialog.css" type="text/css"?>
<?xml-stylesheet href="chrome://branding/content/aboutDialog.css" type="text/css"?>
+<?xml-stylesheet href="chrome://torbutton/skin/aboutDialog.css" type="text/css"?>
+<!-- We need to include the localization DTDs until we migrate to Fluent -->
<!DOCTYPE window [
-#ifdef XP_MACOSX
#include browser-doctype.inc
-#endif
]>
<window xmlns:html="http://www.w3.org/1999/xhtml"
@@ -28,7 +28,7 @@
data-l10n-id="aboutDialog-title"
#endif
role="dialog"
- aria-describedby="version distribution distributionId communityDesc contributeDesc trademark"
+ aria-describedby="version distribution distributionId projectDesc helpDesc trademark trademarkTor"
>
#ifdef XP_MACOSX
#include macWindow.inc.xhtml
@@ -132,24 +132,36 @@
<label is="text-link" useoriginprincipal="true" href="about:credits" data-l10n-name="community-exp-creditsLink"></label>
</description>
</vbox>
- <description class="text-blurb" id="communityDesc" data-l10n-id="community-2">
- <label is="text-link" href="http://www.mozilla.org/" data-l10n-name="community-mozillaLink"></label>
- <label is="text-link" useoriginprincipal="true" href="about:credits" data-l10n-name="community-creditsLink"></label>
+ <!-- Keep communityDesc and contributeDesc to avoid JS errors trying to hide them -->
+ <description class="text-blurb" id="communityDesc" data-l10n-id="community-2" hidden="true"></description>
+ <description class="text-blurb" id="contributeDesc" data-l10n-id="helpus" hidden="true"></description>
+ <description class="text-blurb" id="projectDesc">
+ &project.start;
+ <label is="text-link" href="https://www.torproject.org/">
+ &project.tpoLink;
+ </label>&project.end;
</description>
- <description class="text-blurb" id="contributeDesc" data-l10n-id="helpus">
- <label is="text-link" href="https://donate.mozilla.org/?utm_source=firefox&utm_medium=referral&…" data-l10n-name="helpus-donateLink"></label>
- <label is="text-link" href="http://www.mozilla.org/contribute/" data-l10n-name="helpus-getInvolvedLink"></label>
+ <description class="text-blurb" id="helpDesc">
+ &help.start;
+ <label is="text-link" href="https://donate.torproject.org/">
+ &help.donateLink;
+ </label>
+ &help.or;
+ <label is="text-link" href="https://community.torproject.org/">
+ &help.getInvolvedLink;
+ </label>&help.end;
</description>
</vbox>
</vbox>
</hbox>
<vbox id="bottomBox">
- <hbox pack="center">
- <label is="text-link" class="bottom-link" useoriginprincipal="true" href="about:license" data-l10n-id="bottomLinks-license"></label>
- <label is="text-link" class="bottom-link" useoriginprincipal="true" href="about:rights" data-l10n-id="bottomLinks-rights"></label>
- <label is="text-link" class="bottom-link" href="https://www.mozilla.org/privacy/" data-l10n-id="bottomLinks-privacy"></label>
+ <hbox id="newBottom" pack="center" position="1">
+ <label is="text-link" class="bottom-link" href="https://support.torproject.org/">&bottomLinks.questions;</label>
+ <label is="text-link" class="bottom-link" href="https://community.torproject.org/relay/">&bottomLinks.grow;</label>
+ <label is="text-link" class="bottom-link" useoriginprincipal="true" href="about:license">&bottomLinks.license;</label>
</hbox>
<description id="trademark" data-l10n-id="trademarkInfo"></description>
+ <description id="trademarkTor">&tor.TrademarkStatement;</description>
</vbox>
</vbox>
diff --git a/browser/base/content/browser-doctype.inc b/browser/base/content/browser-doctype.inc
index 9aa278773158..48cf6cd3eda0 100644
--- a/browser/base/content/browser-doctype.inc
+++ b/browser/base/content/browser-doctype.inc
@@ -14,3 +14,9 @@
%syncBrandDTD;
<!ENTITY % brandingsDTD SYSTEM "chrome://browser/locale/brandings.dtd">
%brandingsDTD;
+<!ENTITY % torbuttonDTD SYSTEM "chrome://torbutton/locale/torbutton.dtd">
+%torbuttonDTD;
+<!ENTITY % aboutTorDTD SYSTEM "chrome://torbutton/locale/aboutTor.dtd">
+%aboutTorDTD;
+<!ENTITY % aboutDialogDTD SYSTEM "chrome://torbutton/locale/aboutDialog.dtd">
+%aboutDialogDTD;
diff --git a/browser/base/content/browser-menubar.inc b/browser/base/content/browser-menubar.inc
index 267ec91707ba..6f4aa9289c35 100644
--- a/browser/base/content/browser-menubar.inc
+++ b/browser/base/content/browser-menubar.inc
@@ -33,6 +33,18 @@
command="Tools:NonFissionWindow"
accesskey="s" label="New Non-Fission Window"/>
#endif
+ <menuseparator/>
+ <menuitem id="menu_newIdentity"
+ accesskey="&torbutton.context_menu.new_identity_key;"
+ key="torbutton-new-identity-key"
+ label="&torbutton.context_menu.new_identity;"
+ oncommand="torbutton_new_identity();"/>
+ <menuitem id="menu_newCircuit"
+ accesskey="&torbutton.context_menu.new_circuit_key;"
+ key="torbutton-new-circuit-key"
+ label="&torbutton.context_menu.new_circuit;"
+ oncommand="torbutton_new_circuit();"/>
+ <menuseparator/>
<menuitem id="menu_openLocation"
hidden="true"
command="Browser:OpenLocation"
@@ -455,17 +467,28 @@
#endif
data-l10n-id="menu-help">
<menupopup id="menu_HelpPopup" onpopupshowing="buildHelpMenu();">
- <menuitem id="menu_openHelp"
+ <!-- dummy elements to avoid 'getElementById' errors -->
+ <box id="feedbackPage"/>
+ <box id="helpSafeMode"/>
+ <box id="menu_HelpPopup_reportPhishingtoolmenu"/>
+ <box id="menu_HelpPopup_reportPhishingErrortoolmenu"/>
+ <!-- Add Tor Browser manual link -->
+ <menuitem id="torBrowserUserManual"
+ oncommand="gBrowser.selectedTab = gBrowser.addTab('https://tb-manual.torproject.org/' + Services.locale.requestedLocale, {triggeringPrincipal: Services.scriptSecurityManager.getSystemPrincipal()});"
+ label="&aboutTor.torbrowser_user_manual.label;"
+ accesskey="&aboutTor.torbrowser_user_manual.accesskey;"/>
+ <!-- Bug 18905: Hide unused help menu items -->
+ <!-- <menuitem id="menu_openHelp"
oncommand="openHelpLink('firefox-help')"
onclick="checkForMiddleClick(this, event);"
data-l10n-id="menu-help-product"
#ifdef XP_MACOSX
- key="key_openHelpMac"/>
+ key="key_openHelpMac"/> -->
#else
- />
+ /> -->
#endif
- <menuitem id="menu_openTour"
- oncommand="openTourPage();" data-l10n-id="menu-help-show-tour"/>
+ <!-- <menuitem id="menu_openTour"
+ oncommand="openTourPage();" data-l10n-id="menu-help-show-tour"/> -->
<menuitem id="help_importFromAnotherBrowser"
command="cmd_help_importFromAnotherBrowser" data-l10n-id="menu-help-import-from-another-browser"/>
<menuitem id="menu_keyboardShortcuts"
@@ -474,22 +497,22 @@
<menuitem id="troubleShooting"
oncommand="openTroubleshootingPage()"
onclick="checkForMiddleClick(this, event);" data-l10n-id="menu-help-troubleshooting-info"/>
- <menuitem id="feedbackPage"
+ <!-- <menuitem id="feedbackPage"
oncommand="openFeedbackPage()"
- onclick="checkForMiddleClick(this, event);" data-l10n-id="menu-help-feedback-page"/>
- <menuitem id="helpSafeMode"
- oncommand="safeModeRestart();" data-l10n-id="menu-help-safe-mode-without-addons"/>
- <menuitem id="menu_HelpPopup_reportPhishingtoolmenu"
+ onclick="checkForMiddleClick(this, event);" data-l10n-id="menu-help-feedback-page"/> -->
+ <!-- <menuitem id="helpSafeMode"
+ oncommand="safeModeRestart();" data-l10n-id="menu-help-safe-mode-without-addons"/> -->
+ <!-- <menuitem id="menu_HelpPopup_reportPhishingtoolmenu"
disabled="true"
oncommand="openUILink(gSafeBrowsing.getReportURL('Phish'), event, {triggeringPrincipal: Services.scriptSecurityManager.createNullPrincipal({})});"
onclick="checkForMiddleClick(this, event);"
- hidden="true" data-l10n-id="menu-help-report-deceptive-site"/>
- <menuitem id="menu_HelpPopup_reportPhishingErrortoolmenu"
+ hidden="true" data-l10n-id="menu-help-report-deceptive-site"/> -->
+ <!-- <menuitem id="menu_HelpPopup_reportPhishingErrortoolmenu"
disabled="true"
oncommand="ReportFalseDeceptiveSite();"
onclick="checkForMiddleClick(this, event);"
data-l10n-id="menu-help-not-deceptive"
- hidden="true"/>
+ hidden="true"/> -->
<menuseparator id="helpPolicySeparator"
hidden="true"/>
<menuitem id="helpPolicySupport"
diff --git a/browser/base/content/browser-sets.inc b/browser/base/content/browser-sets.inc
index aae94e8d4654..fa71bfb37a84 100644
--- a/browser/base/content/browser-sets.inc
+++ b/browser/base/content/browser-sets.inc
@@ -374,4 +374,6 @@
data-l10n-id="hide-other-apps-shortcut"
modifiers="accel,alt"/>
#endif
+ <key id="torbutton-new-identity-key" modifiers="accel shift" key="U" oncommand="torbutton_new_identity()"/>
+ <key id="torbutton-new-circuit-key" modifiers="accel shift" key="L" oncommand="torbutton_new_circuit()"/>
</keyset>
diff --git a/browser/base/content/browser.js b/browser/base/content/browser.js
index 5eb38ba78282..3c342dedd5d4 100644
--- a/browser/base/content/browser.js
+++ b/browser/base/content/browser.js
@@ -620,6 +620,7 @@ var gPageIcons = {
};
var gInitialPages = [
+ "about:tor",
"about:blank",
"about:newtab",
"about:home",
diff --git a/browser/base/content/browser.xhtml b/browser/base/content/browser.xhtml
index 62825bfd206a..229fc2a26dd2 100644
--- a/browser/base/content/browser.xhtml
+++ b/browser/base/content/browser.xhtml
@@ -29,6 +29,8 @@
<?xml-stylesheet href="chrome://browser/skin/searchbar.css" type="text/css"?>
<?xml-stylesheet href="chrome://browser/skin/places/tree-icons.css" type="text/css"?>
<?xml-stylesheet href="chrome://browser/skin/places/editBookmark.css" type="text/css"?>
+<?xml-stylesheet href="chrome://torbutton/skin/tor-circuit-display.css" type="text/css"?>
+<?xml-stylesheet href="chrome://torbutton/skin/torbutton.css" type="text/css"?>
# All DTD information is stored in a separate file so that it can be shared by
# hiddenWindowMac.xhtml.
@@ -105,11 +107,18 @@
Services.scriptloader.loadSubScript("chrome://browser/content/places/places-menupopup.js", this);
Services.scriptloader.loadSubScript("chrome://browser/content/search/autocomplete-popup.js", this);
Services.scriptloader.loadSubScript("chrome://browser/content/search/searchbar.js", this);
+ Services.scriptloader.loadSubScript("chrome://torbutton/content/tor-circuit-display.js", this);
+ Services.scriptloader.loadSubScript("chrome://torbutton/content/torbutton.js", this);
window.onload = gBrowserInit.onLoad.bind(gBrowserInit);
window.onunload = gBrowserInit.onUnload.bind(gBrowserInit);
window.onclose = WindowIsClosing;
+ //onLoad Handler
+ try {
+ window.addEventListener("load", torbutton_init, false);
+ } catch (e) {}
+
window.addEventListener("MozBeforeInitialXULLayout",
gBrowserInit.onBeforeInitialXULLayout.bind(gBrowserInit), { once: true });
diff --git a/browser/components/controlcenter/content/identityPanel.inc.xhtml b/browser/components/controlcenter/content/identityPanel.inc.xhtml
index 77c0b9b2413f..a8edda858e41 100644
--- a/browser/components/controlcenter/content/identityPanel.inc.xhtml
+++ b/browser/components/controlcenter/content/identityPanel.inc.xhtml
@@ -60,6 +60,23 @@
oncommand="gIdentityHandler.showSecuritySubView();"/>
</hbox>
+ <!-- Circuit display section -->
+ <hbox id="circuit-display-container" class="identity-popup-section">
+ <vbox id="circuit-display-content" flex="1" role="group"
+ aria-labelledby="circuit-display-headline">
+ <hbox id="circuit-display-header" align="center">
+ <label id="circuit-display-headline"
+ role="heading" aria-level="2">&torbutton.circuit_display.title;</label>
+ </hbox>
+ <html:ul id="circuit-display-nodes" dir="auto"/>
+ </vbox>
+ <vbox id="circuit-reload-content" flex="1">
+ <html:button id="circuit-reload-button"
+ onclick="torbutton_new_circuit()">&torbutton.circuit_display.new_circuit;</html:button>
+ <hbox id="circuit-guard-note-container"/>
+ </vbox>
+ </hbox>
+
<!-- Permissions Section -->
<hbox class="identity-popup-section"
when-connection="not-secure secure secure-ev secure-cert-user-overridden file extension cert-error-page">
diff --git a/browser/components/customizableui/content/panelUI.inc.xhtml b/browser/components/customizableui/content/panelUI.inc.xhtml
index 3a8b74b0a9f3..bdb8a7c227cf 100644
--- a/browser/components/customizableui/content/panelUI.inc.xhtml
+++ b/browser/components/customizableui/content/panelUI.inc.xhtml
@@ -265,7 +265,8 @@
class="subviewbutton subviewbutton-iconic"
label="&newPrivateWindow.label;"
key="key_privatebrowsing"
- command="Tools:PrivateBrowsing"/>
+ command="Tools:PrivateBrowsing"
+ hidden="true"/>
#ifdef NIGHTLY_BUILD
<toolbarbutton id="appMenu-fission-window-button"
class="subviewbutton subviewbutton-iconic"
@@ -281,7 +282,19 @@
<toolbarbutton id="appMenuRestoreLastSession"
label="&appMenuHistory.restoreSession.label;"
class="subviewbutton subviewbutton-iconic"
- command="Browser:RestoreLastSession"/>
+ command="Browser:RestoreLastSession"
+ hidden="true"/>
+ <toolbarseparator/>
+ <toolbarbutton id="appMenuNewIdentity"
+ class="subviewbutton subviewbutton-iconic"
+ key="torbutton-new-identity-key"
+ label="&torbutton.context_menu.new_identity;"
+ oncommand="torbutton_new_identity();"/>
+ <toolbarbutton id="appMenuNewCircuit"
+ class="subviewbutton subviewbutton-iconic"
+ key="torbutton-new-circuit-key"
+ label="&torbutton.context_menu.new_circuit;"
+ oncommand="torbutton_new_circuit();"/>
<toolbarseparator/>
<toolbaritem id="appMenu-zoom-controls" class="toolbaritem-combined-buttons" closemenu="none">
<!-- Use a spacer, because panel sizing code gets confused when using CSS methods. -->
diff --git a/browser/installer/package-manifest.in b/browser/installer/package-manifest.in
index 582a6e13d607..3722bf2ee22b 100644
--- a/browser/installer/package-manifest.in
+++ b/browser/installer/package-manifest.in
@@ -253,6 +253,8 @@
@RESPATH@/browser/chrome/torlauncher/*
@RESPATH@/browser/@PREF_DIR@/torlauncher-prefs.js
#endif
+@RESPATH@/chrome/torbutton.manifest
+@RESPATH@/chrome/torbutton/*
@RESPATH@/chrome/toolkit@JAREXT@
@RESPATH@/chrome/toolkit.manifest
@RESPATH@/chrome/recording.manifest
diff --git a/docshell/base/nsAboutRedirector.cpp b/docshell/base/nsAboutRedirector.cpp
index 730fd6aea654..051f239c76ac 100644
--- a/docshell/base/nsAboutRedirector.cpp
+++ b/docshell/base/nsAboutRedirector.cpp
@@ -146,7 +146,11 @@ static const RedirEntry kRedirMap[] = {
{"crashcontent", "about:blank",
nsIAboutModule::HIDE_FROM_ABOUTABOUT |
nsIAboutModule::URI_CAN_LOAD_IN_CHILD |
- nsIAboutModule::URI_MUST_LOAD_IN_CHILD}};
+ nsIAboutModule::URI_MUST_LOAD_IN_CHILD},
+ {"tor", "chrome://torbutton/content/aboutTor/aboutTor.xhtml",
+ nsIAboutModule::URI_MUST_LOAD_IN_CHILD |
+ nsIAboutModule::URI_SAFE_FOR_UNTRUSTED_CONTENT |
+ nsIAboutModule::ALLOW_SCRIPT}};
static const int kRedirTotal = mozilla::ArrayLength(kRedirMap);
NS_IMETHODIMP
diff --git a/docshell/build/components.conf b/docshell/build/components.conf
index 6d7253d01631..2d56ea33389d 100644
--- a/docshell/build/components.conf
+++ b/docshell/build/components.conf
@@ -27,6 +27,7 @@ about_pages = [
'srcdoc',
'support',
'telemetry',
+ 'tor',
'url-classifier',
'webrtc',
]
diff --git a/mobile/android/installer/package-manifest.in b/mobile/android/installer/package-manifest.in
index 17d6471c4742..055eb4717447 100644
--- a/mobile/android/installer/package-manifest.in
+++ b/mobile/android/installer/package-manifest.in
@@ -137,6 +137,10 @@
@BINPATH@/chrome/devtools@JAREXT@
@BINPATH@/chrome/devtools.manifest
+; Torbutton
+@BINPATH@/chrome/torbutton@JAREXT@
+@BINPATH@/chrome/torbutton.manifest
+
; [Default Preferences]
; All the pref files must be part of base to prevent migration bugs
#ifdef MOZ_GECKOVIEW_JAR
diff --git a/toolkit/moz.build b/toolkit/moz.build
index b6f792da7124..3451334de15c 100644
--- a/toolkit/moz.build
+++ b/toolkit/moz.build
@@ -23,6 +23,7 @@ DIRS += [
'pluginproblem',
'profile',
'themes',
+ 'torproject/torbutton',
]
if CONFIG['OS_ARCH'] == 'WINNT' and CONFIG['MOZ_DEFAULT_BROWSER_AGENT']:
diff --git a/toolkit/mozapps/extensions/internal/XPIProvider.jsm b/toolkit/mozapps/extensions/internal/XPIProvider.jsm
index bcdf6f40d5ed..bf31932b59f1 100644
--- a/toolkit/mozapps/extensions/internal/XPIProvider.jsm
+++ b/toolkit/mozapps/extensions/internal/XPIProvider.jsm
@@ -1462,6 +1462,15 @@ var XPIStates = {
for (let [id, file] of loc.readAddons()) {
knownIds.delete(id);
+ // Uninstall torbutton if it is installed in the user profile
+ if (id === "torbutton(a)torproject.org" &&
+ loc.name === KEY_APP_PROFILE) {
+ logger.debug("Uninstalling torbutton from user profile.");
+ loc.installer.uninstallAddon(id);
+ changed = true;
+ continue;
+ }
+
// Since it is now part of the browser, uninstall the Tor Launcher
// extension. This will remove the Tor Launcher .xpi from user
// profiles on macOS.
diff --git a/toolkit/torproject/torbutton b/toolkit/torproject/torbutton
new file mode 160000
index 000000000000..f5a747e06001
--- /dev/null
+++ b/toolkit/torproject/torbutton
@@ -0,0 +1 @@
+Subproject commit f5a747e06001898e80ef2b0676ed264eb20be349
diff --git a/tools/lint/eslint/eslint-plugin-mozilla/lib/environments/browser-window.js b/tools/lint/eslint/eslint-plugin-mozilla/lib/environments/browser-window.js
index 76e03f2d49bb..2ff107b553b2 100644
--- a/tools/lint/eslint/eslint-plugin-mozilla/lib/environments/browser-window.js
+++ b/tools/lint/eslint/eslint-plugin-mozilla/lib/environments/browser-window.js
@@ -75,7 +75,11 @@ function getGlobalScriptIncludes(scriptPath) {
"browser/components/search/content/"
)
.replace("chrome://browser/content/", "browser/base/content/")
- .replace("chrome://global/content/", "toolkit/content/");
+ .replace("chrome://global/content/", "toolkit/content/")
+ .replace(
+ "chrome://torbutton/content/",
+ "toolkit/torproject/torbutton/chrome/content/"
+ );
for (let mapping of Object.getOwnPropertyNames(MAPPINGS)) {
if (sourceFile.includes(mapping)) {
1
0
[tor-browser/tor-browser-78.12.0esr-11.0-1] Add TorStrings module for localization
by boklm@torproject.org 14 Jul '21
by boklm@torproject.org 14 Jul '21
14 Jul '21
commit f91e7e8fcd6df27476d40884aa77393f9bbcf9c6
Author: Alex Catarineu <acat(a)torproject.org>
Date: Fri Jul 24 21:15:20 2020 +0200
Add TorStrings module for localization
---
browser/modules/TorStrings.jsm | 490 +++++++++++++++++++++++++++++++++++++++++
browser/modules/moz.build | 1 +
2 files changed, 491 insertions(+)
diff --git a/browser/modules/TorStrings.jsm b/browser/modules/TorStrings.jsm
new file mode 100644
index 000000000000..e8a8d37ae373
--- /dev/null
+++ b/browser/modules/TorStrings.jsm
@@ -0,0 +1,490 @@
+"use strict";
+
+var EXPORTED_SYMBOLS = ["TorStrings"];
+
+const { XPCOMUtils } = ChromeUtils.import(
+ "resource://gre/modules/XPCOMUtils.jsm"
+);
+const { Services } = ChromeUtils.import(
+ "resource://gre/modules/Services.jsm"
+);
+const { getLocale } = ChromeUtils.import(
+ "resource://torbutton/modules/utils.js"
+);
+
+XPCOMUtils.defineLazyGlobalGetters(this, ["DOMParser"]);
+XPCOMUtils.defineLazyGetter(this, "domParser", () => {
+ const parser = new DOMParser();
+ parser.forceEnableDTD();
+ return parser;
+});
+
+/*
+ Tor DTD String Bundle
+
+ DTD strings loaded from torbutton/tor-launcher, but provide a fallback in case they aren't available
+*/
+class TorDTDStringBundle {
+ constructor(aBundleURLs, aPrefix) {
+ let locations = [];
+ for (const [index, url] of aBundleURLs.entries()) {
+ locations.push(`<!ENTITY % dtd_${index} SYSTEM "${url}">%dtd_${index};`);
+ }
+ this._locations = locations;
+ this._prefix = aPrefix;
+ }
+
+ // copied from testing/marionette/l10n.js
+ localizeEntity(urls, id) {
+ // Use the DOM parser to resolve the entity and extract its real value
+ let header = `<?xml version="1.0"?><!DOCTYPE elem [${this._locations.join(
+ ""
+ )}]>`;
+ let elem = `<elem id="elementID">&${id};</elem>`;
+ let doc = domParser.parseFromString(header + elem, "text/xml");
+ let element = doc.querySelector("elem[id='elementID']");
+
+ if (element === null) {
+ throw new Error(`Entity with id='${id}' hasn't been found`);
+ }
+
+ return element.textContent;
+ }
+
+ getString(key, fallback) {
+ if (key) {
+ try {
+ return this.localizeEntity(this._bundleURLs, `${this._prefix}${key}`);
+ } catch (e) {}
+ }
+
+ // on failure, assign the fallback if it exists
+ if (fallback) {
+ return fallback;
+ }
+ // otherwise return string key
+ return `$(${key})`;
+ }
+}
+
+/*
+ Tor Property String Bundle
+
+ Property strings loaded from torbutton/tor-launcher, but provide a fallback in case they aren't available
+*/
+class TorPropertyStringBundle {
+ constructor(aBundleURL, aPrefix) {
+ try {
+ this._bundle = Services.strings.createBundle(aBundleURL);
+ } catch (e) {}
+
+ this._prefix = aPrefix;
+ }
+
+ getString(key, fallback) {
+ if (key) {
+ try {
+ return this._bundle.GetStringFromName(`${this._prefix}${key}`);
+ } catch (e) {}
+ }
+
+ // on failure, assign the fallback if it exists
+ if (fallback) {
+ return fallback;
+ }
+ // otherwise return string key
+ return `$(${key})`;
+ }
+}
+
+/*
+ Security Level Strings
+*/
+var TorStrings = {
+ /*
+ Tor Browser Security Level Strings
+ */
+ securityLevel: (function() {
+ let tsb = new TorDTDStringBundle(
+ ["chrome://torbutton/locale/torbutton.dtd"],
+ "torbutton.prefs.sec_"
+ );
+ let getString = function(key, fallback) {
+ return tsb.getString(key, fallback);
+ };
+
+ // read localized strings from torbutton; but use hard-coded en-US strings as fallbacks in case of error
+ let retval = {
+ securityLevel: getString("caption", "Security Level"),
+ customWarning: getString("custom_warning", "Custom"),
+ overview: getString(
+ "overview",
+ "Disable certain web features that can be used to attack your security and anonymity."
+ ),
+ standard: {
+ level: getString("standard_label", "Standard"),
+ tooltip: getString("standard_tooltip", "Security Level : Standard"),
+ summary: getString(
+ "standard_description",
+ "All Tor Browser and website features are enabled."
+ ),
+ },
+ safer: {
+ level: getString("safer_label", "Safer"),
+ tooltip: getString("safer_tooltip", "Security Level : Safer"),
+ summary: getString(
+ "safer_description",
+ "Disables website features that are often dangerous, causing some sites to lose functionality."
+ ),
+ description1: getString(
+ "js_on_https_sites_only",
+ "JavaScript is disabled on non-HTTPS sites."
+ ),
+ description2: getString(
+ "limit_typography",
+ "Some fonts and math symbols are disabled."
+ ),
+ description3: getString(
+ "click_to_play_media",
+ "Audio and video (HTML5 media), and WebGL are click-to-play."
+ ),
+ },
+ safest: {
+ level: getString("safest_label", "Safest"),
+ tooltip: getString("safest_tooltip", "Security Level : Safest"),
+ summary: getString(
+ "safest_description",
+ "Only allows website features required for static sites and basic services. These changes affect images, media, and scripts."
+ ),
+ description1: getString(
+ "js_disabled",
+ "JavaScript is disabled by default on all sites."
+ ),
+ description2: getString(
+ "limit_graphics_and_typography",
+ "Some fonts, icons, math symbols, and images are disabled."
+ ),
+ description3: getString(
+ "click_to_play_media",
+ "Audio and video (HTML5 media), and WebGL are click-to-play."
+ ),
+ },
+ custom: {
+ summary: getString(
+ "custom_summary",
+ "Your custom browser preferences have resulted in unusual security settings. For security and privacy reasons, we recommend you choose one of the default security levels."
+ ),
+ },
+ learnMore: getString("learn_more_label", "Learn more"),
+ learnMoreURL: `https://tb-manual.torproject.org/${getLocale()}/security-settings/`,
+ restoreDefaults: getString("restore_defaults", "Restore Defaults"),
+ advancedSecuritySettings: getString(
+ "advanced_security_settings",
+ "Advanced Security Settings\u2026"
+ ),
+ };
+ return retval;
+ })() /* Security Level Strings */,
+
+ /*
+ Tor about:preferences#tor Strings
+ */
+ settings: (function() {
+ let tsb = new TorDTDStringBundle(
+ ["chrome://torlauncher/locale/network-settings.dtd"],
+ ""
+ );
+ let getString = function(key, fallback) {
+ return tsb.getString(key, fallback);
+ };
+
+ let retval = {
+ categoryTitle: getString("torPreferences.categoryTitle", "Tor"),
+ torPreferencesHeading: getString(
+ "torPreferences.torSettings",
+ "Tor Settings"
+ ),
+ torPreferencesDescription: getString(
+ "torPreferences.torSettingsDescription",
+ "Tor Browser routes your traffic over the Tor Network, run by thousands of volunteers around the world."
+ ),
+ learnMore: getString("torPreferences.learnMore", "Learn More"),
+ bridgesHeading: getString("torPreferences.bridges", "Bridges"),
+ bridgesDescription: getString(
+ "torPreferences.bridgesDescription",
+ "Bridges help you access the Tor Network in places where Tor is blocked. Depending on where you are, one bridge may work better than another."
+ ),
+ useBridge: getString("torPreferences.useBridge", "Use a bridge"),
+ selectBridge: getString(
+ "torsettings.useBridges.default",
+ "Select a bridge"
+ ),
+ requestBridgeFromTorProject: getString(
+ "torsettings.useBridges.bridgeDB",
+ "Request a bridge from torproject.org"
+ ),
+ requestNewBridge: getString(
+ "torPreferences.requestNewBridge",
+ "Request a New Bridge\u2026"
+ ),
+ provideBridge: getString(
+ "torPreferences.provideBridge",
+ "Provide a bridge"
+ ),
+ provideBridgeDirections: getString(
+ "torsettings.useBridges.label",
+ "Enter bridge information from a trusted source."
+ ),
+ provideBridgePlaceholder: getString(
+ "torsettings.useBridges.placeholder",
+ "type address:port (one per line)"
+ ),
+ advancedHeading: getString("torPreferences.advanced", "Advanced"),
+ advancedDescription: getString(
+ "torPreferences.advancedDescription",
+ "Configure how Tor Browser connects to the internet."
+ ),
+ useLocalProxy: getString("torsettings.useProxy.checkbox", "I use a proxy to connect to the Internet"),
+ proxyType: getString("torsettings.useProxy.type", "Proxy Type"),
+ proxyTypeSOCKS4: getString("torsettings.useProxy.type.socks4", "SOCKS4"),
+ proxyTypeSOCKS5: getString("torsettings.useProxy.type.socks5", "SOCKS5"),
+ proxyTypeHTTP: getString("torsettings.useProxy.type.http", "HTTP/HTTPS"),
+ proxyAddress: getString("torsettings.useProxy.address", "Address"),
+ proxyAddressPlaceholder: getString(
+ "torsettings.useProxy.address.placeholder",
+ "IP address or hostname"
+ ),
+ proxyPort: getString("torsettings.useProxy.port", "Port"),
+ proxyUsername: getString("torsettings.useProxy.username", "Username"),
+ proxyPassword: getString("torsettings.useProxy.password", "Password"),
+ proxyUsernamePasswordPlaceholder: getString(
+ "torsettings.optional",
+ "Optional"
+ ),
+ useFirewall: getString(
+ "torsettings.firewall.checkbox",
+ "This computer goes through a firewall that only allows connections to certain ports"
+ ),
+ allowedPorts: getString(
+ "torsettings.firewall.allowedPorts",
+ "Allowed Ports"
+ ),
+ allowedPortsPlaceholder: getString(
+ "torPreferences.firewallPortsPlaceholder",
+ "Comma-seperated values"
+ ),
+ requestBridgeDialogTitle: getString(
+ "torPreferences.requestBridgeDialogTitle",
+ "Request Bridge"
+ ),
+ submitCaptcha: getString(
+ "torsettings.useBridges.captchaSubmit",
+ "Submit"
+ ),
+ contactingBridgeDB: getString(
+ "torPreferences.requestBridgeDialogWaitPrompt",
+ "Contacting BridgeDB. Please Wait."
+ ),
+ solveTheCaptcha: getString(
+ "torPreferences.requestBridgeDialogSolvePrompt",
+ "Solve the CAPTCHA to request a bridge."
+ ),
+ captchaTextboxPlaceholder: getString(
+ "torsettings.useBridges.captchaSolution.placeholder",
+ "Enter the characters from the image"
+ ),
+ incorrectCaptcha: getString(
+ "torPreferences.requestBridgeErrorBadSolution",
+ "The solution is not correct. Please try again."
+ ),
+ showTorDaemonLogs: getString(
+ "torPreferences.viewTorLogs",
+ "View the Tor logs."
+ ),
+ showLogs: getString("torPreferences.viewLogs", "View Logs\u2026"),
+ torLogDialogTitle: getString(
+ "torPreferences.torLogsDialogTitle",
+ "Tor Logs"
+ ),
+ copyLog: getString("torsettings.copyLog", "Copy Tor Log to Clipboard"),
+
+ learnMoreTorBrowserURL: `https://tb-manual.torproject.org/${getLocale()}/about/`,
+ learnMoreBridgesURL: `https://tb-manual.torproject.org/${getLocale()}/bridges/`,
+ learnMoreNetworkSettingsURL: `about:blank`,
+ };
+
+ return retval;
+ })() /* Tor Network Settings Strings */,
+
+ /*
+ Tor Onion Services Strings, e.g., for the authentication prompt.
+ */
+ onionServices: (function() {
+ let tsb = new TorPropertyStringBundle(
+ "chrome://torbutton/locale/torbutton.properties",
+ "onionServices."
+ );
+ let getString = function(key, fallback) {
+ return tsb.getString(key, fallback);
+ };
+
+ const kProblemLoadingSiteFallback = "Problem Loading Onionsite";
+ const kLongDescFallback = "Details: %S";
+
+ let retval = {
+ learnMore: getString("learnMore", "Learn more"),
+ learnMoreURL: `https://support.torproject.org/${getLocale()}/onionservices/client-auth/`,
+ errorPage: {
+ browser: getString("errorPage.browser", "Browser"),
+ network: getString("errorPage.network", "Network"),
+ onionSite: getString("errorPage.onionSite", "Onionsite"),
+ },
+ descNotFound: { // Tor SOCKS error 0xF0
+ pageTitle: getString("descNotFound.pageTitle", kProblemLoadingSiteFallback),
+ header: getString("descNotFound.header", "Onionsite Not Found"),
+ longDescription: getString("descNotFound.longDescription", kLongDescFallback),
+ },
+ descInvalid: { // Tor SOCKS error 0xF1
+ pageTitle: getString("descInvalid.pageTitle", kProblemLoadingSiteFallback),
+ header: getString("descInvalid.header", "Onionsite Cannot Be Reached"),
+ longDescription: getString("descInvalid.longDescription", kLongDescFallback),
+ },
+ introFailed: { // Tor SOCKS error 0xF2
+ pageTitle: getString("introFailed.pageTitle", kProblemLoadingSiteFallback),
+ header: getString("introFailed.header", "Onionsite Has Disconnected"),
+ longDescription: getString("introFailed.longDescription", kLongDescFallback),
+ },
+ rendezvousFailed: { // Tor SOCKS error 0xF3
+ pageTitle: getString("rendezvousFailed.pageTitle", kProblemLoadingSiteFallback),
+ header: getString("rendezvousFailed.header", "Unable to Connect to Onionsite"),
+ longDescription: getString("rendezvousFailed.longDescription", kLongDescFallback),
+ },
+ clientAuthMissing: { // Tor SOCKS error 0xF4
+ pageTitle: getString("clientAuthMissing.pageTitle", "Authorization Required"),
+ header: getString("clientAuthMissing.header", "Onionsite Requires Authentication"),
+ longDescription: getString("clientAuthMissing.longDescription", kLongDescFallback),
+ },
+ clientAuthIncorrect: { // Tor SOCKS error 0xF5
+ pageTitle: getString("clientAuthIncorrect.pageTitle", "Authorization Failed"),
+ header: getString("clientAuthIncorrect.header", "Onionsite Authentication Failed"),
+ longDescription: getString("clientAuthIncorrect.longDescription", kLongDescFallback),
+ },
+ badAddress: { // Tor SOCKS error 0xF6
+ pageTitle: getString("badAddress.pageTitle", kProblemLoadingSiteFallback),
+ header: getString("badAddress.header", "Invalid Onionsite Address"),
+ longDescription: getString("badAddress.longDescription", kLongDescFallback),
+ },
+ introTimedOut: { // Tor SOCKS error 0xF7
+ pageTitle: getString("introTimedOut.pageTitle", kProblemLoadingSiteFallback),
+ header: getString("introTimedOut.header", "Onionsite Circuit Creation Timed Out"),
+ longDescription: getString("introTimedOut.longDescription", kLongDescFallback),
+ },
+ authPrompt: {
+ description:
+ getString("authPrompt.description2", "%S is requesting that you authenticate."),
+ keyPlaceholder: getString("authPrompt.keyPlaceholder", "Enter your key"),
+ done: getString("authPrompt.done", "Done"),
+ doneAccessKey: getString("authPrompt.doneAccessKey", "d"),
+ invalidKey: getString("authPrompt.invalidKey", "Invalid key"),
+ failedToSetKey:
+ getString("authPrompt.failedToSetKey", "Failed to set key"),
+ },
+ authPreferences: {
+ header: getString("authPreferences.header", "Onion Services Authentication"),
+ overview: getString("authPreferences.overview", "Some onion services require that you identify yourself with a key"),
+ savedKeys: getString("authPreferences.savedKeys", "Saved Keys"),
+ dialogTitle: getString("authPreferences.dialogTitle", "Onion Services Keys"),
+ dialogIntro: getString("authPreferences.dialogIntro", "Keys for the following onionsites are stored on your computer"),
+ onionSite: getString("authPreferences.onionSite", "Onionsite"),
+ onionKey: getString("authPreferences.onionKey", "Key"),
+ remove: getString("authPreferences.remove", "Remove"),
+ removeAll: getString("authPreferences.removeAll", "Remove All"),
+ failedToGetKeys: getString("authPreferences.failedToGetKeys", "Failed to get keys"),
+ failedToRemoveKey: getString("authPreferences.failedToRemoveKey", "Failed to remove key"),
+ },
+ };
+
+ return retval;
+ })() /* Tor Onion Services Strings */,
+
+ /*
+ OnionLocation
+ */
+ onionLocation: (function() {
+ const tsb = new TorPropertyStringBundle(
+ ["chrome://torbutton/locale/torbutton.properties"],
+ "onionLocation."
+ );
+ const getString = function(key, fallback) {
+ return tsb.getString(key, fallback);
+ };
+
+ const retval = {
+ alwaysPrioritize: getString(
+ "alwaysPrioritize",
+ "Always Prioritize Onionsites"
+ ),
+ alwaysPrioritizeAccessKey: getString("alwaysPrioritizeAccessKey", "a"),
+ notNow: getString("notNow", "Not Now"),
+ notNowAccessKey: getString("notNowAccessKey", "n"),
+ description: getString(
+ "description",
+ "Website publishers can protect users by adding a security layer. This prevents eavesdroppers from knowing that you are the one visiting that website."
+ ),
+ tryThis: getString("tryThis", "Try this: Onionsite"),
+ onionAvailable: getString("onionAvailable", "Onionsite available"),
+ learnMore: getString("learnMore", "Learn more"),
+ learnMoreURL: `https://tb-manual.torproject.org/${getLocale()}/onion-services/`,
+ always: getString("always", "Always"),
+ askEverytime: getString("askEverytime", "Ask you every time"),
+ prioritizeOnionsDescription: getString(
+ "prioritizeOnionsDescription",
+ "Prioritize onionsites when they are available."
+ ),
+ onionServicesTitle: getString("onionServicesTitle", "Onion Services"),
+ };
+
+ return retval;
+ })() /* OnionLocation */,
+
+ /*
+ Tor Deamon Configuration Key Strings
+ */
+
+ // TODO: proper camel case
+ configKeys: {
+ /* Bridge Conf Settings */
+ useBridges: "UseBridges",
+ bridgeList: "Bridge",
+ /* Proxy Conf Strings */
+ socks4Proxy: "Socks4Proxy",
+ socks5Proxy: "Socks5Proxy",
+ socks5ProxyUsername: "Socks5ProxyUsername",
+ socks5ProxyPassword: "Socks5ProxyPassword",
+ httpsProxy: "HTTPSProxy",
+ httpsProxyAuthenticator: "HTTPSProxyAuthenticator",
+ /* Firewall Conf Strings */
+ reachableAddresses: "ReachableAddresses",
+
+ /* BridgeDB Strings */
+ clientTransportPlugin: "ClientTransportPlugin",
+ },
+
+ /*
+ about:config preference keys
+ */
+
+ preferenceKeys: {
+ defaultBridgeType: "extensions.torlauncher.default_bridge_type",
+ recommendedBridgeType:
+ "extensions.torlauncher.default_bridge_recommended_type",
+ },
+
+ /*
+ about:config preference branches
+ */
+ preferenceBranches: {
+ defaultBridge: "extensions.torlauncher.default_bridge.",
+ bridgeDBBridges: "extensions.torlauncher.bridgedb_bridge.",
+ },
+};
diff --git a/browser/modules/moz.build b/browser/modules/moz.build
index cbb94cf736a0..88f2a55d6f49 100644
--- a/browser/modules/moz.build
+++ b/browser/modules/moz.build
@@ -154,6 +154,7 @@ EXTRA_JS_MODULES += [
'TabUnloader.jsm',
'ThemeVariableMap.jsm',
'TopSiteAttribution.jsm',
+ 'TorStrings.jsm',
'TransientPrefs.jsm',
'webrtcUI.jsm',
'ZoomUI.jsm',
1
0
[tor-browser/tor-browser-78.12.0esr-11.0-1] Bug 13028: Prevent potential proxy bypass cases.
by boklm@torproject.org 14 Jul '21
by boklm@torproject.org 14 Jul '21
14 Jul '21
commit 28b81c11f73b9368a3196a59721ec3dabb30ccd4
Author: Mike Perry <mikeperry-git(a)torproject.org>
Date: Mon Sep 29 14:30:19 2014 -0700
Bug 13028: Prevent potential proxy bypass cases.
It looks like these cases should only be invoked in the NSS command line
tools, and not the browser, but I decided to patch them anyway because there
literally is a maze of network function pointers being passed around, and it's
very hard to tell if some random code might not pass in the proper proxied
versions of the networking code here by accident.
---
security/nss/lib/certhigh/ocsp.c | 8 ++++++++
.../lib/libpkix/pkix_pl_nss/module/pkix_pl_socket.c | 21 +++++++++++++++++++++
2 files changed, 29 insertions(+)
diff --git a/security/nss/lib/certhigh/ocsp.c b/security/nss/lib/certhigh/ocsp.c
index cea8456606bf..86fa971cfbef 100644
--- a/security/nss/lib/certhigh/ocsp.c
+++ b/security/nss/lib/certhigh/ocsp.c
@@ -2932,6 +2932,14 @@ ocsp_ConnectToHost(const char *host, PRUint16 port)
PRNetAddr addr;
char *netdbbuf = NULL;
+ // XXX: Do we need a unittest ifdef here? We don't want to break the tests, but
+ // we want to ensure nothing can ever hit this code in production.
+#if 1
+ printf("Tor Browser BUG: Attempted OSCP direct connect to %s, port %u\n", host,
+ port);
+ goto loser;
+#endif
+
sock = PR_NewTCPSocket();
if (sock == NULL)
goto loser;
diff --git a/security/nss/lib/libpkix/pkix_pl_nss/module/pkix_pl_socket.c b/security/nss/lib/libpkix/pkix_pl_nss/module/pkix_pl_socket.c
index e8698376b5be..85791d84a932 100644
--- a/security/nss/lib/libpkix/pkix_pl_nss/module/pkix_pl_socket.c
+++ b/security/nss/lib/libpkix/pkix_pl_nss/module/pkix_pl_socket.c
@@ -1334,6 +1334,13 @@ pkix_pl_Socket_Create(
plContext),
PKIX_COULDNOTCREATESOCKETOBJECT);
+ // XXX: Do we need a unittest ifdef here? We don't want to break the tests, but
+ // we want to ensure nothing can ever hit this code in production.
+#if 1
+ printf("Tor Browser BUG: Attempted pkix direct socket connect\n");
+ PKIX_ERROR(PKIX_PRNEWTCPSOCKETFAILED);
+#endif
+
socket->isServer = isServer;
socket->timeout = timeout;
socket->clientSock = NULL;
@@ -1433,6 +1440,13 @@ pkix_pl_Socket_CreateByName(
localCopyName = PL_strdup(serverName);
+ // XXX: Do we need a unittest ifdef here? We don't want to break the tests, but
+ // we want to ensure nothing can ever hit this code in production.
+#if 1
+ printf("Tor Browser BUG: Attempted pkix direct connect to %s\n", serverName);
+ PKIX_ERROR(PKIX_PRNEWTCPSOCKETFAILED);
+#endif
+
sepPtr = strchr(localCopyName, ':');
/* First strip off the portnum, if present, from the end of the name */
if (sepPtr) {
@@ -1582,6 +1596,13 @@ pkix_pl_Socket_CreateByHostAndPort(
PKIX_ENTER(SOCKET, "pkix_pl_Socket_CreateByHostAndPort");
PKIX_NULLCHECK_THREE(hostname, pStatus, pSocket);
+ // XXX: Do we need a unittest ifdef here? We don't want to break the tests, but
+ // we want to ensure nothing can ever hit this code in production.
+#if 1
+ printf("Tor Browser BUG: Attempted pkix direct connect to %s, port %u\n", hostname,
+ portnum);
+ PKIX_ERROR(PKIX_PRNEWTCPSOCKETFAILED);
+#endif
prstatus = PR_GetHostByName(hostname, buf, sizeof(buf), &hostent);
1
0
[tor-browser/tor-browser-78.12.0esr-11.0-1] Bug 14631: Improve profile access error messages.
by boklm@torproject.org 14 Jul '21
by boklm@torproject.org 14 Jul '21
14 Jul '21
commit 4cf9e1ae1e005610b77dd69f6b6fc6d8e3d44f24
Author: Kathy Brade <brade(a)pearlcrescent.com>
Date: Tue Feb 24 13:50:23 2015 -0500
Bug 14631: Improve profile access error messages.
Instead of always reporting that the profile is locked, display specific
messages for "access denied" and "read-only file system".
To allow for localization, get profile-related error strings from Torbutton.
Use app display name ("Tor Browser") in profile-related error alerts.
---
.../mozapps/profile/profileSelection.properties | 5 +
toolkit/profile/nsToolkitProfileService.cpp | 57 +++++++-
toolkit/profile/nsToolkitProfileService.h | 13 +-
toolkit/xre/nsAppRunner.cpp | 155 ++++++++++++++++++---
4 files changed, 207 insertions(+), 23 deletions(-)
diff --git a/toolkit/locales/en-US/chrome/mozapps/profile/profileSelection.properties b/toolkit/locales/en-US/chrome/mozapps/profile/profileSelection.properties
index 2be092bf4c4b..922b52cb1385 100644
--- a/toolkit/locales/en-US/chrome/mozapps/profile/profileSelection.properties
+++ b/toolkit/locales/en-US/chrome/mozapps/profile/profileSelection.properties
@@ -12,6 +12,11 @@ restartMessageUnlocker=%S is already running, but is not responding. The old %S
restartMessageNoUnlockerMac=A copy of %S is already open. Only one copy of %S can be open at a time.
restartMessageUnlockerMac=A copy of %S is already open. The running copy of %S will quit in order to open this one.
+# LOCALIZATION NOTE (profileProblemTitle, profileReadOnly, profileReadOnlyMac, profileAccessDenied): Messages displayed when the browser profile cannot be accessed or written to. %S is the application name.
+profileProblemTitle=%S Profile Problem
+profileReadOnly=You cannot run %S from a read-only file system. Please copy %S to another location before trying to use it.
+profileReadOnlyMac=You cannot run %S from a read-only file system. Please copy %S to your Desktop or Applications folder before trying to use it.
+profileAccessDenied=%S does not have permission to access the profile. Please adjust your file system permissions and try again.
# Profile manager
# LOCALIZATION NOTE (profileTooltip): First %S is the profile name, second %S is the path to the profile folder.
profileTooltip=Profile: ‘%S’ - Path: ‘%S’
diff --git a/toolkit/profile/nsToolkitProfileService.cpp b/toolkit/profile/nsToolkitProfileService.cpp
index a3e50f8c00d3..3f32bd95f9c9 100644
--- a/toolkit/profile/nsToolkitProfileService.cpp
+++ b/toolkit/profile/nsToolkitProfileService.cpp
@@ -1161,9 +1161,10 @@ nsToolkitProfileService::SelectStartupProfile(
}
bool wasDefault;
+ ProfileStatus profileStatus;
nsresult rv =
SelectStartupProfile(&argc, argv.get(), aIsResetting, aRootDir, aLocalDir,
- aProfile, aDidCreate, &wasDefault);
+ aProfile, aDidCreate, &wasDefault, profileStatus);
// Since we were called outside of the normal startup path complete any
// startup tasks.
@@ -1196,7 +1197,8 @@ nsToolkitProfileService::SelectStartupProfile(
nsresult nsToolkitProfileService::SelectStartupProfile(
int* aArgc, char* aArgv[], bool aIsResetting, nsIFile** aRootDir,
nsIFile** aLocalDir, nsIToolkitProfile** aProfile, bool* aDidCreate,
- bool* aWasDefaultSelection) {
+ bool* aWasDefaultSelection, ProfileStatus& aProfileStatus) {
+ aProfileStatus = PROFILE_STATUS_OK;
if (mStartupProfileSelected) {
return NS_ERROR_ALREADY_INITIALIZED;
}
@@ -1290,6 +1292,13 @@ nsresult nsToolkitProfileService::SelectStartupProfile(
rv = XRE_GetFileFromPath(arg, getter_AddRefs(lf));
NS_ENSURE_SUCCESS(rv, rv);
+ aProfileStatus = CheckProfileWriteAccess(lf);
+ if (PROFILE_STATUS_OK != aProfileStatus) {
+ NS_ADDREF(*aRootDir = lf);
+ NS_ADDREF(*aLocalDir = lf);
+ return NS_ERROR_FAILURE;
+ }
+
// Make sure that the profile path exists and it's a directory.
bool exists;
rv = lf->Exists(&exists);
@@ -2079,3 +2088,47 @@ nsresult XRE_GetFileFromPath(const char* aPath, nsIFile** aResult) {
# error Platform-specific logic needed here.
#endif
}
+
+// Check for write permission to the profile directory by trying to create a
+// new file (after ensuring that no file with the same name exists).
+ProfileStatus nsToolkitProfileService::CheckProfileWriteAccess(
+ nsIFile* aProfileDir) {
+#if defined(XP_UNIX)
+ NS_NAMED_LITERAL_STRING(writeTestFileName, ".parentwritetest");
+#else
+ NS_NAMED_LITERAL_STRING(writeTestFileName, "parent.writetest");
+#endif
+
+ nsCOMPtr<nsIFile> writeTestFile;
+ nsresult rv = aProfileDir->Clone(getter_AddRefs(writeTestFile));
+ if (NS_SUCCEEDED(rv)) rv = writeTestFile->Append(writeTestFileName);
+
+ if (NS_SUCCEEDED(rv)) {
+ bool doesExist = false;
+ rv = writeTestFile->Exists(&doesExist);
+ if (NS_SUCCEEDED(rv) && doesExist) rv = writeTestFile->Remove(true);
+ }
+
+ if (NS_SUCCEEDED(rv)) {
+ rv = writeTestFile->Create(nsIFile::NORMAL_FILE_TYPE, 0666);
+ (void)writeTestFile->Remove(true);
+ }
+
+ ProfileStatus status =
+ NS_SUCCEEDED(rv) ? PROFILE_STATUS_OK : PROFILE_STATUS_OTHER_ERROR;
+ if (NS_ERROR_FILE_ACCESS_DENIED == rv)
+ status = PROFILE_STATUS_ACCESS_DENIED;
+ else if (NS_ERROR_FILE_READ_ONLY == rv)
+ status = PROFILE_STATUS_READ_ONLY;
+
+ return status;
+}
+
+ProfileStatus nsToolkitProfileService::CheckProfileWriteAccess(
+ nsIToolkitProfile* aProfile) {
+ nsCOMPtr<nsIFile> profileDir;
+ nsresult rv = aProfile->GetRootDir(getter_AddRefs(profileDir));
+ if (NS_FAILED(rv)) return PROFILE_STATUS_OTHER_ERROR;
+
+ return CheckProfileWriteAccess(profileDir);
+}
diff --git a/toolkit/profile/nsToolkitProfileService.h b/toolkit/profile/nsToolkitProfileService.h
index f2a238312b95..cfb1964ee1d7 100644
--- a/toolkit/profile/nsToolkitProfileService.h
+++ b/toolkit/profile/nsToolkitProfileService.h
@@ -15,6 +15,14 @@
#include "nsProfileLock.h"
#include "nsINIParser.h"
+enum ProfileStatus {
+ PROFILE_STATUS_OK,
+ PROFILE_STATUS_ACCESS_DENIED,
+ PROFILE_STATUS_READ_ONLY,
+ PROFILE_STATUS_IS_LOCKED,
+ PROFILE_STATUS_OTHER_ERROR
+};
+
class nsToolkitProfile final
: public nsIToolkitProfile,
public mozilla::LinkedListElement<RefPtr<nsToolkitProfile>> {
@@ -79,10 +87,13 @@ class nsToolkitProfileService final : public nsIToolkitProfileService {
nsresult SelectStartupProfile(int* aArgc, char* aArgv[], bool aIsResetting,
nsIFile** aRootDir, nsIFile** aLocalDir,
nsIToolkitProfile** aProfile, bool* aDidCreate,
- bool* aWasDefaultSelection);
+ bool* aWasDefaultSelection,
+ ProfileStatus& aProfileStatus);
nsresult CreateResetProfile(nsIToolkitProfile** aNewProfile);
nsresult ApplyResetProfile(nsIToolkitProfile* aOldProfile);
void CompleteStartup();
+ static ProfileStatus CheckProfileWriteAccess(nsIToolkitProfile* aProfile);
+ static ProfileStatus CheckProfileWriteAccess(nsIFile* aProfileDir);
private:
friend class nsToolkitProfile;
diff --git a/toolkit/xre/nsAppRunner.cpp b/toolkit/xre/nsAppRunner.cpp
index e3e7f785ada9..8de43a8c4cfc 100644
--- a/toolkit/xre/nsAppRunner.cpp
+++ b/toolkit/xre/nsAppRunner.cpp
@@ -1731,6 +1731,91 @@ nsresult LaunchChild(bool aBlankCommandLine) {
return NS_ERROR_LAUNCHED_CHILD_PROCESS;
}
+static nsresult GetOverrideStringBundleForLocale(nsIStringBundleService* aSBS,
+ const char* aTorbuttonURI,
+ const char* aLocale,
+ nsIStringBundle** aResult) {
+ NS_ENSURE_ARG(aSBS);
+ NS_ENSURE_ARG(aTorbuttonURI);
+ NS_ENSURE_ARG(aLocale);
+ NS_ENSURE_ARG(aResult);
+
+ const char* kFormatStr =
+ "jar:%s!/chrome/torbutton/locale/%s/torbutton.properties";
+ nsPrintfCString strBundleURL(kFormatStr, aTorbuttonURI, aLocale);
+ nsresult rv = aSBS->CreateBundle(strBundleURL.get(), aResult);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ // To ensure that we have a valid string bundle, try to retrieve a string
+ // that we know exists.
+ nsAutoString val;
+ rv = (*aResult)->GetStringFromName("profileProblemTitle", val);
+ if (!NS_SUCCEEDED(rv)) *aResult = nullptr; // No good. Discard it.
+
+ return rv;
+}
+
+static void GetOverrideStringBundle(nsIStringBundleService* aSBS,
+ nsIStringBundle** aResult) {
+ if (!aSBS || !aResult) return;
+
+ *aResult = nullptr;
+
+ // Build Torbutton file URI string by starting from GREDir.
+ RefPtr<nsXREDirProvider> dirProvider = nsXREDirProvider::GetSingleton();
+ if (!dirProvider) return;
+
+ nsCOMPtr<nsIFile> greDir = dirProvider->GetGREDir();
+ if (!greDir) return;
+
+ // Create file URI, extract as string, and append omni.ja relative path.
+ nsCOMPtr<nsIURI> uri;
+ nsAutoCString uriString;
+ if (NS_FAILED(NS_NewFileURI(getter_AddRefs(uri), greDir)) ||
+ NS_FAILED(uri->GetSpec(uriString))) {
+ return;
+ }
+
+ uriString.Append("omni.ja");
+
+ nsAutoCString userAgentLocale;
+ if (!NS_SUCCEEDED(
+ Preferences::GetCString("intl.locale.requested", userAgentLocale))) {
+ return;
+ }
+
+ nsresult rv = GetOverrideStringBundleForLocale(
+ aSBS, uriString.get(), userAgentLocale.get(), aResult);
+ if (NS_FAILED(rv)) {
+ // Try again using base locale, e.g., "en" vs. "en-US".
+ int16_t offset = userAgentLocale.FindChar('-', 1);
+ if (offset > 0) {
+ nsAutoCString shortLocale(Substring(userAgentLocale, 0, offset));
+ rv = GetOverrideStringBundleForLocale(aSBS, uriString.get(),
+ shortLocale.get(), aResult);
+ }
+ }
+}
+
+static nsresult GetFormattedString(nsIStringBundle* aOverrideBundle,
+ nsIStringBundle* aMainBundle,
+ const char* aName,
+ const nsTArray<nsString>& aParams,
+ nsAString& aResult) {
+ NS_ENSURE_ARG(aName);
+
+ nsresult rv = NS_ERROR_FAILURE;
+ if (aOverrideBundle) {
+ rv = aOverrideBundle->FormatStringFromName(aName, aParams, aResult);
+ }
+
+ // If string was not found in override bundle, use main (browser) bundle.
+ if (NS_FAILED(rv) && aMainBundle)
+ rv = aMainBundle->FormatStringFromName(aName, aParams, aResult);
+
+ return rv;
+}
+
static const char kProfileProperties[] =
"chrome://mozapps/locale/profile/profileSelection.properties";
@@ -1779,7 +1864,7 @@ static nsresult ProfileMissingDialog(nsINativeAppSupport* aNative) {
sbs->CreateBundle(kProfileProperties, getter_AddRefs(sb));
NS_ENSURE_TRUE_LOG(sbs, NS_ERROR_FAILURE);
- NS_ConvertUTF8toUTF16 appName(gAppData->name);
+ NS_ConvertUTF8toUTF16 appName(MOZ_APP_DISPLAYNAME);
AutoTArray<nsString, 2> params = {appName, appName};
// profileMissing
@@ -1801,11 +1886,12 @@ static nsresult ProfileMissingDialog(nsINativeAppSupport* aNative) {
}
}
-static ReturnAbortOnError ProfileLockedDialog(nsIFile* aProfileDir,
- nsIFile* aProfileLocalDir,
- nsIProfileUnlocker* aUnlocker,
- nsINativeAppSupport* aNative,
- nsIProfileLock** aResult) {
+static ReturnAbortOnError ProfileErrorDialog(nsIFile* aProfileDir,
+ nsIFile* aProfileLocalDir,
+ ProfileStatus aStatus,
+ nsIProfileUnlocker* aUnlocker,
+ nsINativeAppSupport* aNative,
+ nsIProfileLock** aResult) {
nsresult rv;
bool exists;
@@ -1833,24 +1919,39 @@ static ReturnAbortOnError ProfileLockedDialog(nsIFile* aProfileDir,
sbs->CreateBundle(kProfileProperties, getter_AddRefs(sb));
NS_ENSURE_TRUE_LOG(sbs, NS_ERROR_FAILURE);
- NS_ConvertUTF8toUTF16 appName(gAppData->name);
+ nsCOMPtr<nsIStringBundle> overrideSB;
+ GetOverrideStringBundle(sbs, getter_AddRefs(overrideSB));
+
+ NS_ConvertUTF8toUTF16 appName(MOZ_APP_DISPLAYNAME);
AutoTArray<nsString, 3> params = {appName, appName, appName};
nsAutoString killMessage;
#ifndef XP_MACOSX
- rv = sb->FormatStringFromName(
- aUnlocker ? "restartMessageUnlocker" : "restartMessageNoUnlocker2",
- params, killMessage);
+ static const char kRestartUnlocker[] = "restartMessageUnlocker";
+ static const char kRestartNoUnlocker[] = "restartMessageNoUnlocker2";
+ static const char kReadOnly[] = "profileReadOnly";
#else
- rv = sb->FormatStringFromName(
- aUnlocker ? "restartMessageUnlockerMac" : "restartMessageNoUnlockerMac",
- params, killMessage);
+ static const char kRestartUnlocker[] = "restartMessageUnlockerMac";
+ static const char kRestartNoUnlocker[] = "restartMessageNoUnlockerMac";
+ static const char kReadOnly[] = "profileReadOnlyMac";
#endif
+ static const char kAccessDenied[] = "profileAccessDenied";
+
+ const char* errorKey = aUnlocker ? kRestartUnlocker : kRestartNoUnlocker;
+ if (PROFILE_STATUS_READ_ONLY == aStatus)
+ errorKey = kReadOnly;
+ else if (PROFILE_STATUS_ACCESS_DENIED == aStatus)
+ errorKey = kAccessDenied;
+ rv = GetFormattedString(overrideSB, sb, errorKey, params, killMessage);
NS_ENSURE_SUCCESS(rv, NS_ERROR_FAILURE);
+ const char* titleKey = ((PROFILE_STATUS_READ_ONLY == aStatus) ||
+ (PROFILE_STATUS_ACCESS_DENIED == aStatus))
+ ? "profileProblemTitle"
+ : "restartTitle";
params.SetLength(1);
nsAutoString killTitle;
- rv = sb->FormatStringFromName("restartTitle", params, killTitle);
+ rv = sb->FormatStringFromName(titleKey, params, killTitle);
NS_ENSURE_SUCCESS(rv, NS_ERROR_FAILURE);
if (gfxPlatform::IsHeadless()) {
@@ -2008,6 +2109,13 @@ static nsCOMPtr<nsIToolkitProfile> gResetOldProfile;
static nsresult LockProfile(nsINativeAppSupport* aNative, nsIFile* aRootDir,
nsIFile* aLocalDir, nsIToolkitProfile* aProfile,
nsIProfileLock** aResult) {
+ ProfileStatus status =
+ (aProfile ? nsToolkitProfileService::CheckProfileWriteAccess(aProfile)
+ : nsToolkitProfileService::CheckProfileWriteAccess(aRootDir));
+ if (PROFILE_STATUS_OK != status)
+ return ProfileErrorDialog(aRootDir, aLocalDir, status, nullptr, aNative,
+ aResult);
+
// If you close Firefox and very quickly reopen it, the old Firefox may
// still be closing down. Rather than immediately showing the
// "Firefox is running but is not responding" message, we spend a few
@@ -2034,7 +2142,8 @@ static nsresult LockProfile(nsINativeAppSupport* aNative, nsIFile* aRootDir,
} while (TimeStamp::Now() - start <
TimeDuration::FromSeconds(kLockRetrySeconds));
- return ProfileLockedDialog(aRootDir, aLocalDir, unlocker, aNative, aResult);
+ return ProfileErrorDialog(aRootDir, aLocalDir, PROFILE_STATUS_IS_LOCKED,
+ unlocker, aNative, aResult);
}
// Pick a profile. We need to end up with a profile root dir, local dir and
@@ -2049,7 +2158,8 @@ static nsresult LockProfile(nsINativeAppSupport* aNative, nsIFile* aRootDir,
static nsresult SelectProfile(nsToolkitProfileService* aProfileSvc,
nsINativeAppSupport* aNative, nsIFile** aRootDir,
nsIFile** aLocalDir, nsIToolkitProfile** aProfile,
- bool* aWasDefaultSelection) {
+ bool* aWasDefaultSelection,
+ nsIProfileLock** aResult) {
StartupTimeline::Record(StartupTimeline::SELECT_PROFILE);
nsresult rv;
@@ -2095,9 +2205,14 @@ static nsresult SelectProfile(nsToolkitProfileService* aProfileSvc,
// Ask the profile manager to select the profile directories to use.
bool didCreate = false;
- rv = aProfileSvc->SelectStartupProfile(&gArgc, gArgv, gDoProfileReset,
- aRootDir, aLocalDir, aProfile,
- &didCreate, aWasDefaultSelection);
+ ProfileStatus profileStatus = PROFILE_STATUS_OK;
+ rv = aProfileSvc->SelectStartupProfile(
+ &gArgc, gArgv, gDoProfileReset, aRootDir, aLocalDir, aProfile, &didCreate,
+ aWasDefaultSelection, profileStatus);
+ if (PROFILE_STATUS_OK != profileStatus) {
+ return ProfileErrorDialog(*aRootDir, *aLocalDir, profileStatus, nullptr,
+ aNative, aResult);
+ }
if (rv == NS_ERROR_SHOW_PROFILE_MANAGER) {
return ShowProfileManager(aProfileSvc, aNative);
@@ -3927,7 +4042,7 @@ int XREMain::XRE_mainStartup(bool* aExitFlag) {
nsCOMPtr<nsIToolkitProfile> profile;
rv = SelectProfile(mProfileSvc, mNativeApp, getter_AddRefs(mProfD),
getter_AddRefs(mProfLD), getter_AddRefs(profile),
- &wasDefaultSelection);
+ &wasDefaultSelection, getter_AddRefs(mProfileLock));
if (rv == NS_ERROR_LAUNCHED_CHILD_PROCESS || rv == NS_ERROR_ABORT) {
*aExitFlag = true;
return 0;
1
0
[tor-browser/tor-browser-78.12.0esr-11.0-1] Bug 12974: Disable NTLM and Negotiate HTTP Auth
by boklm@torproject.org 14 Jul '21
by boklm@torproject.org 14 Jul '21
14 Jul '21
commit e51ea662fec39a23c1e6cce0ad6346da26c74d6c
Author: Mike Perry <mikeperry-git(a)torproject.org>
Date: Wed Aug 27 15:19:10 2014 -0700
Bug 12974: Disable NTLM and Negotiate HTTP Auth
This is technically an embargoed Mozilla bug, so I probably shouldn't provide
too many details.
Suffice to say that NTLM and Negotiate auth are bad for Tor users, and I doubt
very many (or any of them) actually need it.
The Mozilla bug is https://bugzilla.mozilla.org/show_bug.cgi?id=1046421
---
extensions/auth/nsHttpNegotiateAuth.cpp | 4 ++++
netwerk/protocol/http/nsHttpNTLMAuth.cpp | 3 +++
2 files changed, 7 insertions(+)
diff --git a/extensions/auth/nsHttpNegotiateAuth.cpp b/extensions/auth/nsHttpNegotiateAuth.cpp
index 99720475b9dd..1c08fcf3da7e 100644
--- a/extensions/auth/nsHttpNegotiateAuth.cpp
+++ b/extensions/auth/nsHttpNegotiateAuth.cpp
@@ -152,6 +152,10 @@ nsHttpNegotiateAuth::ChallengeReceived(nsIHttpAuthenticableChannel* authChannel,
nsIAuthModule* rawModule = (nsIAuthModule*)*continuationState;
*identityInvalid = false;
+
+ /* Always fail Negotiate auth for Tor Browser. We don't need it. */
+ return NS_ERROR_ABORT;
+
if (rawModule) {
return NS_OK;
}
diff --git a/netwerk/protocol/http/nsHttpNTLMAuth.cpp b/netwerk/protocol/http/nsHttpNTLMAuth.cpp
index 0a30de051014..891aaadfd758 100644
--- a/netwerk/protocol/http/nsHttpNTLMAuth.cpp
+++ b/netwerk/protocol/http/nsHttpNTLMAuth.cpp
@@ -168,6 +168,9 @@ nsHttpNTLMAuth::ChallengeReceived(nsIHttpAuthenticableChannel* channel,
*identityInvalid = false;
+ /* Always fail Negotiate auth for Tor Browser. We don't need it. */
+ return NS_ERROR_ABORT;
+
// Start a new auth sequence if the challenge is exactly "NTLM".
// If native NTLM auth apis are available and enabled through prefs,
// try to use them.
1
0
[tor-browser/tor-browser-78.12.0esr-11.0-1] Bug 16439: Remove screencasting code
by boklm@torproject.org 14 Jul '21
by boklm@torproject.org 14 Jul '21
14 Jul '21
commit 62fc099224201682f771bf342c13046c1ee62747
Author: Kathy Brade <brade(a)pearlcrescent.com>
Date: Wed Jun 24 11:01:11 2015 -0400
Bug 16439: Remove screencasting code
We avoid including the screencasting code on mobile (it got ripped out
for desktop in bug 1393582) by simply excluding the related JS modules
from Tor Browser.
---
toolkit/modules/moz.build | 9 +++++----
1 file changed, 5 insertions(+), 4 deletions(-)
diff --git a/toolkit/modules/moz.build b/toolkit/modules/moz.build
index f000f35c126f..e1f1eb5759c5 100644
--- a/toolkit/modules/moz.build
+++ b/toolkit/modules/moz.build
@@ -260,10 +260,11 @@ if 'Android' != CONFIG['OS_TARGET']:
]
else:
DEFINES['ANDROID'] = True
- EXTRA_JS_MODULES += [
- 'secondscreen/RokuApp.jsm',
- 'secondscreen/SimpleServiceDiscovery.jsm',
- ]
+ if not CONFIG['TOR_BROWSER_VERSION']:
+ EXTRA_JS_MODULES += [
+ 'secondscreen/RokuApp.jsm',
+ 'secondscreen/SimpleServiceDiscovery.jsm',
+ ]
if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'windows':
1
0
[tor-browser/tor-browser-78.12.0esr-11.0-1] Bug 9173: Change the default Firefox profile directory to be TBB-relative.
by boklm@torproject.org 14 Jul '21
by boklm@torproject.org 14 Jul '21
14 Jul '21
commit c6a5f9b3367d6e4328b5f52d417288051902408b
Author: Kathy Brade <brade(a)pearlcrescent.com>
Date: Fri Oct 18 15:20:06 2013 -0400
Bug 9173: Change the default Firefox profile directory to be TBB-relative.
This should eliminate our need to rely on a wrapper script that
sets /Users/arthur and launches Firefox with -profile.
---
toolkit/profile/nsToolkitProfileService.cpp | 5 +-
toolkit/xre/nsAppRunner.cpp | 2 +-
toolkit/xre/nsConsoleWriter.cpp | 2 +-
toolkit/xre/nsXREDirProvider.cpp | 150 ++++++----------------------
toolkit/xre/nsXREDirProvider.h | 16 +--
xpcom/io/nsAppFileLocationProvider.cpp | 97 +++++++-----------
6 files changed, 84 insertions(+), 188 deletions(-)
diff --git a/toolkit/profile/nsToolkitProfileService.cpp b/toolkit/profile/nsToolkitProfileService.cpp
index dc4811313b5e..a3e50f8c00d3 100644
--- a/toolkit/profile/nsToolkitProfileService.cpp
+++ b/toolkit/profile/nsToolkitProfileService.cpp
@@ -723,10 +723,11 @@ nsresult nsToolkitProfileService::Init() {
NS_ASSERTION(gDirServiceProvider, "No dirserviceprovider!");
nsresult rv;
- rv = nsXREDirProvider::GetUserAppDataDirectory(getter_AddRefs(mAppData));
+ rv = gDirServiceProvider->GetUserAppDataDirectory(getter_AddRefs(mAppData));
NS_ENSURE_SUCCESS(rv, rv);
- rv = nsXREDirProvider::GetUserLocalDataDirectory(getter_AddRefs(mTempData));
+ rv =
+ gDirServiceProvider->GetUserLocalDataDirectory(getter_AddRefs(mTempData));
NS_ENSURE_SUCCESS(rv, rv);
rv = mAppData->Clone(getter_AddRefs(mProfileDBFile));
diff --git a/toolkit/xre/nsAppRunner.cpp b/toolkit/xre/nsAppRunner.cpp
index 8b5bce27cdc4..e3e7f785ada9 100644
--- a/toolkit/xre/nsAppRunner.cpp
+++ b/toolkit/xre/nsAppRunner.cpp
@@ -3182,7 +3182,7 @@ int XREMain::XRE_mainInit(bool* aExitFlag) {
if ((mAppData->flags & NS_XRE_ENABLE_CRASH_REPORTER) &&
NS_SUCCEEDED(CrashReporter::SetExceptionHandler(xreBinDirectory))) {
nsCOMPtr<nsIFile> file;
- rv = nsXREDirProvider::GetUserAppDataDirectory(getter_AddRefs(file));
+ rv = mDirProvider.GetUserAppDataDirectory(getter_AddRefs(file));
if (NS_SUCCEEDED(rv)) {
CrashReporter::SetUserAppDataDirectory(file);
}
diff --git a/toolkit/xre/nsConsoleWriter.cpp b/toolkit/xre/nsConsoleWriter.cpp
index 0a2c0c342893..46735a293a00 100644
--- a/toolkit/xre/nsConsoleWriter.cpp
+++ b/toolkit/xre/nsConsoleWriter.cpp
@@ -29,7 +29,7 @@ void WriteConsoleLog() {
} else {
if (!gLogConsoleErrors) return;
- rv = nsXREDirProvider::GetUserAppDataDirectory(getter_AddRefs(lfile));
+ rv = gDirServiceProvider->GetUserAppDataDirectory(getter_AddRefs(lfile));
if (NS_FAILED(rv)) return;
lfile->AppendNative(NS_LITERAL_CSTRING("console.log"));
diff --git a/toolkit/xre/nsXREDirProvider.cpp b/toolkit/xre/nsXREDirProvider.cpp
index 7641ef683c39..f80cb2827349 100644
--- a/toolkit/xre/nsXREDirProvider.cpp
+++ b/toolkit/xre/nsXREDirProvider.cpp
@@ -32,6 +32,7 @@
#include "nsArrayEnumerator.h"
#include "nsEnumeratorUtils.h"
#include "nsReadableUtils.h"
+#include "nsXPCOMPrivate.h" // for XPCOM_FILE_PATH_SEPARATOR
#include "SpecialSystemDirectory.h"
@@ -249,9 +250,6 @@ nsresult nsXREDirProvider::GetUserProfilesRootDir(nsIFile** aResult) {
nsresult rv = GetUserDataDirectory(getter_AddRefs(file), false);
if (NS_SUCCEEDED(rv)) {
-#if !defined(XP_UNIX) || defined(XP_MACOSX)
- rv = file->AppendNative(NS_LITERAL_CSTRING("Profiles"));
-#endif
// We must create the profile directory here if it does not exist.
nsresult tmp = EnsureDirectoryExists(file);
if (NS_FAILED(tmp)) {
@@ -267,9 +265,6 @@ nsresult nsXREDirProvider::GetUserProfilesLocalDir(nsIFile** aResult) {
nsresult rv = GetUserDataDirectory(getter_AddRefs(file), true);
if (NS_SUCCEEDED(rv)) {
-#if !defined(XP_UNIX) || defined(XP_MACOSX)
- rv = file->AppendNative(NS_LITERAL_CSTRING("Profiles"));
-#endif
// We must create the profile directory here if it does not exist.
nsresult tmp = EnsureDirectoryExists(file);
if (NS_FAILED(tmp)) {
@@ -1403,7 +1398,7 @@ nsresult nsXREDirProvider::SetUserDataProfileDirectory(nsCOMPtr<nsIFile>& aFile,
nsresult nsXREDirProvider::GetUserDataDirectoryHome(nsIFile** aFile,
bool aLocal) {
// Copied from nsAppFileLocationProvider (more or less)
- nsresult rv;
+ NS_ENSURE_ARG_POINTER(aFile);
nsCOMPtr<nsIFile> localDir;
if (aLocal && gDataDirHomeLocal) {
@@ -1413,81 +1408,39 @@ nsresult nsXREDirProvider::GetUserDataDirectoryHome(nsIFile** aFile,
return gDataDirHome->Clone(aFile);
}
-#if defined(XP_MACOSX)
- FSRef fsRef;
- OSType folderType;
- if (aLocal) {
- folderType = kCachedDataFolderType;
- } else {
-# ifdef MOZ_THUNDERBIRD
- folderType = kDomainLibraryFolderType;
-# else
- folderType = kApplicationSupportFolderType;
-# endif
- }
- OSErr err = ::FSFindFolder(kUserDomain, folderType, kCreateFolder, &fsRef);
- NS_ENSURE_FALSE(err, NS_ERROR_FAILURE);
-
- rv = NS_NewNativeLocalFile(EmptyCString(), true, getter_AddRefs(localDir));
+ nsresult rv = GetAppDir()->Clone(getter_AddRefs(localDir));
NS_ENSURE_SUCCESS(rv, rv);
- nsCOMPtr<nsILocalFileMac> dirFileMac = do_QueryInterface(localDir);
- NS_ENSURE_TRUE(dirFileMac, NS_ERROR_UNEXPECTED);
-
- rv = dirFileMac->InitWithFSRef(&fsRef);
- NS_ENSURE_SUCCESS(rv, rv);
+ int levelsToRemove = 1; // In FF21+, appDir points to browser subdirectory.
+#if defined(XP_MACOSX)
+ levelsToRemove += 2;
+#endif
+ while (localDir && (levelsToRemove > 0)) {
+ // When crawling up the hierarchy, components named "." do not count.
+ nsAutoCString removedName;
+ rv = localDir->GetNativeLeafName(removedName);
+ NS_ENSURE_SUCCESS(rv, rv);
+ bool didRemove = !removedName.Equals(".");
- localDir = dirFileMac;
-#elif defined(XP_IOS)
- nsAutoCString userDir;
- if (GetUIKitDirectory(aLocal, userDir)) {
- rv = NS_NewNativeLocalFile(userDir, true, getter_AddRefs(localDir));
- } else {
- rv = NS_ERROR_FAILURE;
- }
- NS_ENSURE_SUCCESS(rv, rv);
-#elif defined(XP_WIN)
- nsString path;
- if (aLocal) {
- rv = GetShellFolderPath(FOLDERID_LocalAppData, path);
- if (NS_FAILED(rv)) rv = GetRegWindowsAppDataFolder(aLocal, path);
- }
- if (!aLocal || NS_FAILED(rv)) {
- rv = GetShellFolderPath(FOLDERID_RoamingAppData, path);
- if (NS_FAILED(rv)) {
- if (!aLocal) rv = GetRegWindowsAppDataFolder(aLocal, path);
- }
+ // Remove a directory component.
+ nsCOMPtr<nsIFile> parentDir;
+ rv = localDir->GetParent(getter_AddRefs(parentDir));
+ NS_ENSURE_SUCCESS(rv, rv);
+ localDir = parentDir;
+ if (didRemove) --levelsToRemove;
}
- NS_ENSURE_SUCCESS(rv, rv);
- rv = NS_NewLocalFile(path, true, getter_AddRefs(localDir));
-#elif defined(XP_UNIX)
- const char* homeDir = getenv("HOME");
- if (!homeDir || !*homeDir) return NS_ERROR_FAILURE;
+ if (!localDir) return NS_ERROR_FAILURE;
-# ifdef ANDROID /* We want (ProfD == ProfLD) on Android. */
- aLocal = false;
-# endif
+ rv = localDir->AppendRelativeNativePath(
+ NS_LITERAL_CSTRING("TorBrowser" XPCOM_FILE_PATH_SEPARATOR
+ "Data" XPCOM_FILE_PATH_SEPARATOR "Browser"));
+ NS_ENSURE_SUCCESS(rv, rv);
if (aLocal) {
- // If $XDG_CACHE_HOME is defined use it, otherwise use $HOME/.cache.
- const char* cacheHome = getenv("XDG_CACHE_HOME");
- if (cacheHome && *cacheHome) {
- rv = NS_NewNativeLocalFile(nsDependentCString(cacheHome), true,
- getter_AddRefs(localDir));
- } else {
- rv = NS_NewNativeLocalFile(nsDependentCString(homeDir), true,
- getter_AddRefs(localDir));
- if (NS_SUCCEEDED(rv))
- rv = localDir->AppendNative(NS_LITERAL_CSTRING(".cache"));
- }
- } else {
- rv = NS_NewNativeLocalFile(nsDependentCString(homeDir), true,
- getter_AddRefs(localDir));
+ rv = localDir->AppendNative(NS_LITERAL_CSTRING("Caches"));
+ NS_ENSURE_SUCCESS(rv, rv);
}
-#else
-# error "Don't know how to get product dir on your platform"
-#endif
NS_IF_ADDREF(*aFile = localDir);
return rv;
@@ -1670,39 +1623,23 @@ nsresult nsXREDirProvider::AppendProfilePath(nsIFile* aFile, bool aLocal) {
}
nsAutoCString profile;
- nsAutoCString appName;
- nsAutoCString vendor;
if (gAppData->profile) {
profile = gAppData->profile;
- } else {
- appName = gAppData->name;
- vendor = gAppData->vendor;
}
- nsresult rv = NS_OK;
+ nsresult rv = NS_ERROR_FAILURE;
#if defined(XP_MACOSX)
if (!profile.IsEmpty()) {
rv = AppendProfileString(aFile, profile.get());
- } else {
- // Note that MacOS ignores the vendor when creating the profile hierarchy -
- // all application preferences directories live alongside one another in
- // ~/Library/Application Support/
- rv = aFile->AppendNative(appName);
+ NS_ENSURE_SUCCESS(rv, rv);
}
- NS_ENSURE_SUCCESS(rv, rv);
#elif defined(XP_WIN)
if (!profile.IsEmpty()) {
rv = AppendProfileString(aFile, profile.get());
- } else {
- if (!vendor.IsEmpty()) {
- rv = aFile->AppendNative(vendor);
- NS_ENSURE_SUCCESS(rv, rv);
- }
- rv = aFile->AppendNative(appName);
+ NS_ENSURE_SUCCESS(rv, rv);
}
- NS_ENSURE_SUCCESS(rv, rv);
#elif defined(ANDROID)
// The directory used for storing profiles
@@ -1712,11 +1649,6 @@ nsresult nsXREDirProvider::AppendProfilePath(nsIFile* aFile, bool aLocal) {
rv = aFile->AppendNative(nsDependentCString("mozilla"));
NS_ENSURE_SUCCESS(rv, rv);
#elif defined(XP_UNIX)
- nsAutoCString folder;
- // Make it hidden (by starting with "."), except when local (the
- // profile is already under ~/.cache or XDG_CACHE_HOME).
- if (!aLocal) folder.Assign('.');
-
if (!profile.IsEmpty()) {
// Skip any leading path characters
const char* profileStart = profile.get();
@@ -1724,32 +1656,16 @@ nsresult nsXREDirProvider::AppendProfilePath(nsIFile* aFile, bool aLocal) {
// On the off chance that someone wanted their folder to be hidden don't
// let it become ".."
- if (*profileStart == '.' && !aLocal) profileStart++;
+ if (*profileStart == '.') profileStart++;
+ // Make it hidden (by starting with ".").
+ nsAutoCString folder(".");
folder.Append(profileStart);
ToLowerCase(folder);
rv = AppendProfileString(aFile, folder.BeginReading());
- } else {
- if (!vendor.IsEmpty()) {
- folder.Append(vendor);
- ToLowerCase(folder);
-
- rv = aFile->AppendNative(folder);
- NS_ENSURE_SUCCESS(rv, rv);
-
- folder.Truncate();
- }
-
- // This can be the case in tests.
- if (!appName.IsEmpty()) {
- folder.Append(appName);
- ToLowerCase(folder);
-
- rv = aFile->AppendNative(folder);
- }
+ NS_ENSURE_SUCCESS(rv, rv);
}
- NS_ENSURE_SUCCESS(rv, rv);
#else
# error "Don't know how to get profile path on your platform"
diff --git a/toolkit/xre/nsXREDirProvider.h b/toolkit/xre/nsXREDirProvider.h
index e55b4e153c56..b9678d4ec577 100644
--- a/toolkit/xre/nsXREDirProvider.h
+++ b/toolkit/xre/nsXREDirProvider.h
@@ -63,15 +63,19 @@ class nsXREDirProvider final : public nsIDirectoryServiceProvider2,
void DoShutdown();
- static nsresult GetUserAppDataDirectory(nsIFile** aFile) {
+ nsresult GetUserAppDataDirectory(nsIFile** aFile) {
return GetUserDataDirectory(aFile, false);
}
- static nsresult GetUserLocalDataDirectory(nsIFile** aFile) {
+ nsresult GetUserLocalDataDirectory(nsIFile** aFile) {
return GetUserDataDirectory(aFile, true);
}
// GetUserDataDirectory gets the profile path from gAppData.
- static nsresult GetUserDataDirectory(nsIFile** aFile, bool aLocal);
+
+ // This function now calls GetAppDir(), so it cannot be static anymore.
+ // The same happens with all the functions (in)directly calling this one (the
+ // rest of Get*Directory functions in this file)
+ nsresult GetUserDataDirectory(nsIFile** aFile, bool aLocal);
/* make sure you clone it, if you need to do stuff to it */
nsIFile* GetGREDir() { return mGREDir; }
@@ -112,9 +116,9 @@ class nsXREDirProvider final : public nsIDirectoryServiceProvider2,
protected:
nsresult GetFilesInternal(const char* aProperty,
nsISimpleEnumerator** aResult);
- static nsresult GetUserDataDirectoryHome(nsIFile** aFile, bool aLocal);
- static nsresult GetSysUserExtensionsDirectory(nsIFile** aFile);
- static nsresult GetSysUserExtensionsDevDirectory(nsIFile** aFile);
+ nsresult GetUserDataDirectoryHome(nsIFile** aFile, bool aLocal);
+ nsresult GetSysUserExtensionsDirectory(nsIFile** aFile);
+ nsresult GetSysUserExtensionsDevDirectory(nsIFile** aFile);
#if defined(XP_UNIX) || defined(XP_MACOSX)
static nsresult GetSystemExtensionsDirectory(nsIFile** aFile);
#endif
diff --git a/xpcom/io/nsAppFileLocationProvider.cpp b/xpcom/io/nsAppFileLocationProvider.cpp
index 915e8bc7361e..81551a8e3893 100644
--- a/xpcom/io/nsAppFileLocationProvider.cpp
+++ b/xpcom/io/nsAppFileLocationProvider.cpp
@@ -15,6 +15,7 @@
#include "nsSimpleEnumerator.h"
#include "prenv.h"
#include "nsCRT.h"
+#include "nsXPCOMPrivate.h" // for XPCOM_FILE_PATH_SEPARATOR
#if defined(MOZ_WIDGET_COCOA)
# include <Carbon/Carbon.h>
# include "nsILocalFileMac.h"
@@ -233,9 +234,8 @@ nsresult nsAppFileLocationProvider::CloneMozBinDirectory(nsIFile** aLocalFile) {
// GetProductDirectory - Gets the directory which contains the application data
// folder
//
-// UNIX : ~/.mozilla/
-// WIN : <Application Data folder on user's machine>\Mozilla
-// Mac : :Documents:Mozilla:
+// UNIX and WIN : <App Folder>/TorBrowser/Data/Browser
+// Mac : <App Folder>/../../TorBrowser/Data/Browser
//----------------------------------------------------------------------------------------
nsresult nsAppFileLocationProvider::GetProductDirectory(nsIFile** aLocalFile,
bool aLocal) {
@@ -247,49 +247,45 @@ nsresult nsAppFileLocationProvider::GetProductDirectory(nsIFile** aLocalFile,
bool exists;
nsCOMPtr<nsIFile> localDir;
-#if defined(MOZ_WIDGET_COCOA)
- FSRef fsRef;
- OSType folderType =
- aLocal ? (OSType)kCachedDataFolderType : (OSType)kDomainLibraryFolderType;
- OSErr err = ::FSFindFolder(kUserDomain, folderType, kCreateFolder, &fsRef);
- if (err) {
- return NS_ERROR_FAILURE;
+ rv = CloneMozBinDirectory(getter_AddRefs(localDir));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ int levelsToRemove = 1; // In FF21+, bin dir points to browser subdirectory.
+#if defined(XP_MACOSX)
+ levelsToRemove += 2;
+#endif
+ while (localDir && (levelsToRemove > 0)) {
+ // When crawling up the hierarchy, components named "." do not count.
+ nsAutoCString removedName;
+ rv = localDir->GetNativeLeafName(removedName);
+ NS_ENSURE_SUCCESS(rv, rv);
+ bool didRemove = !removedName.Equals(".");
+
+ // Remove a directory component.
+ nsCOMPtr<nsIFile> parentDir;
+ rv = localDir->GetParent(getter_AddRefs(parentDir));
+ NS_ENSURE_SUCCESS(rv, rv);
+ localDir = parentDir;
+
+ if (didRemove) {
+ --levelsToRemove;
+ }
}
- NS_NewLocalFile(EmptyString(), true, getter_AddRefs(localDir));
+
if (!localDir) {
return NS_ERROR_FAILURE;
}
- nsCOMPtr<nsILocalFileMac> localDirMac(do_QueryInterface(localDir));
- rv = localDirMac->InitWithFSRef(&fsRef);
- if (NS_FAILED(rv)) {
- return rv;
- }
-#elif defined(XP_WIN)
- nsCOMPtr<nsIProperties> directoryService =
- do_GetService(NS_DIRECTORY_SERVICE_CONTRACTID, &rv);
- if (NS_FAILED(rv)) {
- return rv;
- }
- const char* prop = aLocal ? NS_WIN_LOCAL_APPDATA_DIR : NS_WIN_APPDATA_DIR;
- rv = directoryService->Get(prop, NS_GET_IID(nsIFile),
- getter_AddRefs(localDir));
- if (NS_FAILED(rv)) {
- return rv;
- }
-#elif defined(XP_UNIX)
- rv = NS_NewNativeLocalFile(nsDependentCString(PR_GetEnv("HOME")), true,
- getter_AddRefs(localDir));
- if (NS_FAILED(rv)) {
- return rv;
- }
-#else
-# error dont_know_how_to_get_product_dir_on_your_platform
-#endif
- rv = localDir->AppendRelativeNativePath(DEFAULT_PRODUCT_DIR);
- if (NS_FAILED(rv)) {
- return rv;
+ rv = localDir->AppendRelativeNativePath(
+ NS_LITERAL_CSTRING("TorBrowser" XPCOM_FILE_PATH_SEPARATOR
+ "Data" XPCOM_FILE_PATH_SEPARATOR "Browser"));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ if (aLocal) {
+ rv = localDir->AppendNative(NS_LITERAL_CSTRING("Caches"));
+ NS_ENSURE_SUCCESS(rv, rv);
}
+
rv = localDir->Exists(&exists);
if (NS_SUCCEEDED(rv) && !exists) {
@@ -308,10 +304,6 @@ nsresult nsAppFileLocationProvider::GetProductDirectory(nsIFile** aLocalFile,
//----------------------------------------------------------------------------------------
// GetDefaultUserProfileRoot - Gets the directory which contains each user
// profile dir
-//
-// UNIX : ~/.mozilla/
-// WIN : <Application Data folder on user's machine>\Mozilla\Profiles
-// Mac : :Documents:Mozilla:Profiles:
//----------------------------------------------------------------------------------------
nsresult nsAppFileLocationProvider::GetDefaultUserProfileRoot(
nsIFile** aLocalFile, bool aLocal) {
@@ -327,23 +319,6 @@ nsresult nsAppFileLocationProvider::GetDefaultUserProfileRoot(
return rv;
}
-#if defined(MOZ_WIDGET_COCOA) || defined(XP_WIN)
- // These 3 platforms share this part of the path - do them as one
- rv = localDir->AppendRelativeNativePath(NS_LITERAL_CSTRING("Profiles"));
- if (NS_FAILED(rv)) {
- return rv;
- }
-
- bool exists;
- rv = localDir->Exists(&exists);
- if (NS_SUCCEEDED(rv) && !exists) {
- rv = localDir->Create(nsIFile::DIRECTORY_TYPE, 0775);
- }
- if (NS_FAILED(rv)) {
- return rv;
- }
-#endif
-
localDir.forget(aLocalFile);
return rv;
1
0
[tor-browser/tor-browser-78.12.0esr-11.0-1] Bug 13252: Do not store data in the app bundle
by boklm@torproject.org 14 Jul '21
by boklm@torproject.org 14 Jul '21
14 Jul '21
commit 4224ffb11eb968cd36555fe04896c4c37f88e417
Author: Kathy Brade <brade(a)pearlcrescent.com>
Date: Fri Mar 18 14:20:02 2016 -0400
Bug 13252: Do not store data in the app bundle
When --enable-tor-browser-data-outside-app-dir is enabled,
all user data is stored in a directory named
TorBrowser-Data which is located next to the application directory.
Display an informative error message if the TorBrowser-Data
directory cannot be created due to an "access denied" or a
"read only volume" error.
On Mac OS, add support for the --invisible command line option which
is used by the meek-http-helper to avoid showing an icon for the
helper browser on the dock.
---
toolkit/xre/nsAppRunner.cpp | 76 +++++++++++++++---
toolkit/xre/nsXREDirProvider.cpp | 43 +++++-----
toolkit/xre/nsXREDirProvider.h | 6 ++
xpcom/io/TorFileUtils.cpp | 142 +++++++++++++++++++++++++++++++++
xpcom/io/TorFileUtils.h | 33 ++++++++
xpcom/io/moz.build | 5 ++
xpcom/io/nsAppFileLocationProvider.cpp | 53 +++++-------
7 files changed, 290 insertions(+), 68 deletions(-)
diff --git a/toolkit/xre/nsAppRunner.cpp b/toolkit/xre/nsAppRunner.cpp
index 8de43a8c4cfc..9854332f6917 100644
--- a/toolkit/xre/nsAppRunner.cpp
+++ b/toolkit/xre/nsAppRunner.cpp
@@ -1886,6 +1886,8 @@ static nsresult ProfileMissingDialog(nsINativeAppSupport* aNative) {
}
}
+// If aUnlocker is NULL, it is also OK for the following arguments to be NULL:
+// aProfileDir, aProfileLocalDir, aResult.
static ReturnAbortOnError ProfileErrorDialog(nsIFile* aProfileDir,
nsIFile* aProfileLocalDir,
ProfileStatus aStatus,
@@ -1894,17 +1896,19 @@ static ReturnAbortOnError ProfileErrorDialog(nsIFile* aProfileDir,
nsIProfileLock** aResult) {
nsresult rv;
- bool exists;
- aProfileDir->Exists(&exists);
- if (!exists) {
- return ProfileMissingDialog(aNative);
+ if (aProfileDir) {
+ bool exists;
+ aProfileDir->Exists(&exists);
+ if (!exists) {
+ return ProfileMissingDialog(aNative);
+ }
}
ScopedXPCOMStartup xpcom;
rv = xpcom.Initialize();
NS_ENSURE_SUCCESS(rv, rv);
- mozilla::Telemetry::WriteFailedProfileLock(aProfileDir);
+ if (aProfileDir) mozilla::Telemetry::WriteFailedProfileLock(aProfileDir);
rv = xpcom.SetWindowCreator(aNative);
NS_ENSURE_SUCCESS(rv, NS_ERROR_FAILURE);
@@ -1994,7 +1998,8 @@ static ReturnAbortOnError ProfileErrorDialog(nsIFile* aProfileDir,
}
} else {
#ifdef MOZ_WIDGET_ANDROID
- if (java::GeckoAppShell::UnlockProfile()) {
+ if (aProfileDir && aProfileLocalDir && aResult &&
+ java::GeckoAppShell::UnlockProfile()) {
return NS_LockProfilePath(aProfileDir, aProfileLocalDir, nullptr,
aResult);
}
@@ -2102,6 +2107,23 @@ static ReturnAbortOnError ShowProfileManager(
return LaunchChild(false);
}
+#ifdef TOR_BROWSER_DATA_OUTSIDE_APP_DIR
+static ProfileStatus CheckTorBrowserDataWriteAccess(nsIFile* aAppDir) {
+ // Check whether we can write to the directory that will contain
+ // TorBrowser-Data.
+ nsCOMPtr<nsIFile> tbDataDir;
+ RefPtr<nsXREDirProvider> dirProvider = nsXREDirProvider::GetSingleton();
+ if (!dirProvider) return PROFILE_STATUS_OTHER_ERROR;
+ nsresult rv =
+ dirProvider->GetTorBrowserUserDataDir(getter_AddRefs(tbDataDir));
+ NS_ENSURE_SUCCESS(rv, PROFILE_STATUS_OTHER_ERROR);
+ nsCOMPtr<nsIFile> tbDataDirParent;
+ rv = tbDataDir->GetParent(getter_AddRefs(tbDataDirParent));
+ NS_ENSURE_SUCCESS(rv, PROFILE_STATUS_OTHER_ERROR);
+ return nsToolkitProfileService::CheckProfileWriteAccess(tbDataDirParent);
+}
+#endif
+
static bool gDoMigration = false;
static bool gDoProfileReset = false;
static nsCOMPtr<nsIToolkitProfile> gResetOldProfile;
@@ -3178,6 +3200,14 @@ int XREMain::XRE_mainInit(bool* aExitFlag) {
if (PR_GetEnv("XRE_MAIN_BREAK")) NS_BREAK();
#endif
+#if defined(XP_MACOSX) && defined(TOR_BROWSER_DATA_OUTSIDE_APP_DIR)
+ bool hideDockIcon = (CheckArg("invisible") == ARG_FOUND);
+ if (hideDockIcon) {
+ ProcessSerialNumber psn = {0, kCurrentProcess};
+ TransformProcessType(&psn, kProcessTransformToBackgroundApplication);
+ }
+#endif
+
IncreaseDescriptorLimits();
#ifdef USE_GLX_TEST
@@ -4026,7 +4056,34 @@ int XREMain::XRE_mainStartup(bool* aExitFlag) {
return 0;
}
+#if (defined(MOZ_UPDATER) && !defined(MOZ_WIDGET_ANDROID)) || \
+ defined(TOR_BROWSER_DATA_OUTSIDE_APP_DIR)
+ nsCOMPtr<nsIFile> exeFile, exeDir;
+ bool persistent;
+ rv = mDirProvider.GetFile(XRE_EXECUTABLE_FILE, &persistent,
+ getter_AddRefs(exeFile));
+ NS_ENSURE_SUCCESS(rv, 1);
+ rv = exeFile->GetParent(getter_AddRefs(exeDir));
+ NS_ENSURE_SUCCESS(rv, 1);
+#endif
+
rv = NS_NewToolkitProfileService(getter_AddRefs(mProfileSvc));
+#ifdef TOR_BROWSER_DATA_OUTSIDE_APP_DIR
+ if (NS_FAILED(rv)) {
+ // NS_NewToolkitProfileService() returns a generic NS_ERROR_FAILURE error
+ // if creation of the TorBrowser-Data directory fails due to access denied
+ // or because of a read-only disk volume. Do an extra check here to detect
+ // these errors so we can display an informative error message.
+ ProfileStatus status = CheckTorBrowserDataWriteAccess(exeDir);
+ if ((PROFILE_STATUS_ACCESS_DENIED == status) ||
+ (PROFILE_STATUS_READ_ONLY == status)) {
+ ProfileErrorDialog(nullptr, nullptr, status, nullptr, mNativeApp,
+ nullptr);
+ return 1;
+ }
+ }
+ #endif
+
if (rv == NS_ERROR_FILE_ACCESS_DENIED) {
PR_fprintf(PR_STDERR,
"Error: Access was denied while trying to open files in "
@@ -4095,7 +4152,6 @@ int XREMain::XRE_mainStartup(bool* aExitFlag) {
#if defined(MOZ_UPDATER) && !defined(MOZ_WIDGET_ANDROID)
// Check for and process any available updates
nsCOMPtr<nsIFile> updRoot;
- bool persistent;
rv = mDirProvider.GetFile(XRE_UPDATE_ROOT_DIR, &persistent,
getter_AddRefs(updRoot));
// XRE_UPDATE_ROOT_DIR may fail. Fallback to appDir if failed
@@ -4131,12 +4187,6 @@ int XREMain::XRE_mainStartup(bool* aExitFlag) {
if (CheckArg("test-process-updates")) {
SaveToEnv("MOZ_TEST_PROCESS_UPDATES=1");
}
- nsCOMPtr<nsIFile> exeFile, exeDir;
- rv = mDirProvider.GetFile(XRE_EXECUTABLE_FILE, &persistent,
- getter_AddRefs(exeFile));
- NS_ENSURE_SUCCESS(rv, 1);
- rv = exeFile->GetParent(getter_AddRefs(exeDir));
- NS_ENSURE_SUCCESS(rv, 1);
ProcessUpdates(mDirProvider.GetGREDir(), exeDir, updRoot, gRestartArgc,
gRestartArgv, mAppData->version);
if (EnvHasValue("MOZ_TEST_PROCESS_UPDATES")) {
diff --git a/toolkit/xre/nsXREDirProvider.cpp b/toolkit/xre/nsXREDirProvider.cpp
index f80cb2827349..335a340ea3e9 100644
--- a/toolkit/xre/nsXREDirProvider.cpp
+++ b/toolkit/xre/nsXREDirProvider.cpp
@@ -51,6 +51,8 @@
# include "nsIPK11Token.h"
#endif
+#include "TorFileUtils.h"
+
#include <stdlib.h>
#ifdef XP_WIN
@@ -1408,34 +1410,18 @@ nsresult nsXREDirProvider::GetUserDataDirectoryHome(nsIFile** aFile,
return gDataDirHome->Clone(aFile);
}
- nsresult rv = GetAppDir()->Clone(getter_AddRefs(localDir));
+ nsresult rv = GetTorBrowserUserDataDir(getter_AddRefs(localDir));
NS_ENSURE_SUCCESS(rv, rv);
- int levelsToRemove = 1; // In FF21+, appDir points to browser subdirectory.
-#if defined(XP_MACOSX)
- levelsToRemove += 2;
-#endif
- while (localDir && (levelsToRemove > 0)) {
- // When crawling up the hierarchy, components named "." do not count.
- nsAutoCString removedName;
- rv = localDir->GetNativeLeafName(removedName);
- NS_ENSURE_SUCCESS(rv, rv);
- bool didRemove = !removedName.Equals(".");
-
- // Remove a directory component.
- nsCOMPtr<nsIFile> parentDir;
- rv = localDir->GetParent(getter_AddRefs(parentDir));
- NS_ENSURE_SUCCESS(rv, rv);
- localDir = parentDir;
- if (didRemove) --levelsToRemove;
- }
-
- if (!localDir) return NS_ERROR_FAILURE;
-
+#if !defined(ANDROID)
+#ifdef TOR_BROWSER_DATA_OUTSIDE_APP_DIR
+ rv = localDir->AppendNative(NS_LITERAL_CSTRING("Browser"));
+#else
rv = localDir->AppendRelativeNativePath(
- NS_LITERAL_CSTRING("TorBrowser" XPCOM_FILE_PATH_SEPARATOR
- "Data" XPCOM_FILE_PATH_SEPARATOR "Browser"));
+ NS_LITERAL_CSTRING("Data" XPCOM_FILE_PATH_SEPARATOR "Browser"));
+#endif
NS_ENSURE_SUCCESS(rv, rv);
+#endif
if (aLocal) {
rv = localDir->AppendNative(NS_LITERAL_CSTRING("Caches"));
@@ -1541,6 +1527,15 @@ nsresult nsXREDirProvider::GetUserDataDirectory(nsIFile** aFile, bool aLocal) {
return NS_OK;
}
+nsresult nsXREDirProvider::GetTorBrowserUserDataDir(nsIFile** aFile) {
+ NS_ENSURE_ARG_POINTER(aFile);
+ nsCOMPtr<nsIFile> exeFile;
+ bool per = false;
+ nsresult rv = GetFile(XRE_EXECUTABLE_FILE, &per, getter_AddRefs(exeFile));
+ NS_ENSURE_SUCCESS(rv, rv);
+ return TorBrowser_GetUserDataDir(exeFile, aFile);
+}
+
nsresult nsXREDirProvider::EnsureDirectoryExists(nsIFile* aDirectory) {
nsresult rv = aDirectory->Create(nsIFile::DIRECTORY_TYPE, 0700);
diff --git a/toolkit/xre/nsXREDirProvider.h b/toolkit/xre/nsXREDirProvider.h
index b9678d4ec577..2aa2face5974 100644
--- a/toolkit/xre/nsXREDirProvider.h
+++ b/toolkit/xre/nsXREDirProvider.h
@@ -113,6 +113,12 @@ class nsXREDirProvider final : public nsIDirectoryServiceProvider2,
*/
nsresult GetProfileDir(nsIFile** aResult);
+ /**
+ * Get the TorBrowser user data directory by calling the
+ * TorBrowser_GetUserDataDir() utility function.
+ */
+ nsresult GetTorBrowserUserDataDir(nsIFile** aFile);
+
protected:
nsresult GetFilesInternal(const char* aProperty,
nsISimpleEnumerator** aResult);
diff --git a/xpcom/io/TorFileUtils.cpp b/xpcom/io/TorFileUtils.cpp
new file mode 100644
index 000000000000..bddf8d7bbd95
--- /dev/null
+++ b/xpcom/io/TorFileUtils.cpp
@@ -0,0 +1,142 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * 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/. */
+
+#include "TorFileUtils.h"
+#include "nsString.h"
+#ifdef MOZ_WIDGET_COCOA
+#include <Carbon/Carbon.h>
+#include "nsILocalFileMac.h"
+#endif
+
+static nsresult GetAppRootDir(nsIFile *aExeFile, nsIFile** aFile);
+
+//-----------------------------------------------------------------------------
+nsresult
+TorBrowser_GetUserDataDir(nsIFile *aExeFile, nsIFile** aFile)
+{
+ NS_ENSURE_ARG_POINTER(aFile);
+ nsCOMPtr<nsIFile> tbDataDir;
+
+#ifdef TOR_BROWSER_DATA_OUTSIDE_APP_DIR
+ nsAutoCString tbDataLeafName(NS_LITERAL_CSTRING("TorBrowser-Data"));
+ nsCOMPtr<nsIFile> appRootDir;
+ nsresult rv = GetAppRootDir(aExeFile, getter_AddRefs(appRootDir));
+ NS_ENSURE_SUCCESS(rv, rv);
+#ifndef XP_MACOSX
+ // On all platforms except Mac OS, we always operate in a "portable" mode
+ // where the TorBrowser-Data directory is located next to the application.
+ rv = appRootDir->GetParent(getter_AddRefs(tbDataDir));
+ NS_ENSURE_SUCCESS(rv, rv);
+ rv = tbDataDir->AppendNative(tbDataLeafName);
+ NS_ENSURE_SUCCESS(rv, rv);
+#else
+ // For Mac OS, determine whether we should store user data in the OS's
+ // standard location (i.e., under ~/Library/Application Support). We use
+ // the OS location if (1) the application is installed in a directory whose
+ // path contains "/Applications" or (2) the TorBrowser-Data directory does
+ // not exist and cannot be created (which probably means we lack write
+ // permission to the directory that contains the application).
+ nsAutoString appRootPath;
+ rv = appRootDir->GetPath(appRootPath);
+ NS_ENSURE_SUCCESS(rv, rv);
+ bool useOSLocation = (appRootPath.Find("/Applications",
+ true /* ignore case */) >= 0);
+ if (!useOSLocation) {
+ // We hope to use the portable (aka side-by-side) approach, but before we
+ // commit to that, let's ensure that we can create the TorBrowser-Data
+ // directory. If it already exists, we will try to use it; if not and we
+ // fail to create it, we will switch to ~/Library/Application Support.
+ rv = appRootDir->GetParent(getter_AddRefs(tbDataDir));
+ NS_ENSURE_SUCCESS(rv, rv);
+ rv = tbDataDir->AppendNative(tbDataLeafName);
+ NS_ENSURE_SUCCESS(rv, rv);
+ bool exists = false;
+ rv = tbDataDir->Exists(&exists);
+ if (NS_SUCCEEDED(rv) && !exists)
+ rv = tbDataDir->Create(nsIFile::DIRECTORY_TYPE, 0700);
+ useOSLocation = NS_FAILED(rv);
+ }
+
+ if (useOSLocation) {
+ // We are using ~/Library/Application Support/TorBrowser-Data. We do not
+ // need to create that directory here because the code in nsXREDirProvider
+ // will do so (and the user should always have write permission for
+ // ~/Library/Application Support; if they do not we have no more options).
+ FSRef fsRef;
+ OSErr err = ::FSFindFolder(kUserDomain, kApplicationSupportFolderType,
+ kCreateFolder, &fsRef);
+ NS_ENSURE_FALSE(err, NS_ERROR_FAILURE);
+ // To convert the FSRef returned by FSFindFolder() into an nsIFile that
+ // points to ~/Library/Application Support, we first create an empty
+ // nsIFile object (no path) and then use InitWithFSRef() to set the
+ // path.
+ rv = NS_NewNativeLocalFile(EmptyCString(), true,
+ getter_AddRefs(tbDataDir));
+ NS_ENSURE_SUCCESS(rv, rv);
+ nsCOMPtr<nsILocalFileMac> dirFileMac = do_QueryInterface(tbDataDir);
+ if (!dirFileMac)
+ return NS_ERROR_UNEXPECTED;
+ rv = dirFileMac->InitWithFSRef(&fsRef);
+ NS_ENSURE_SUCCESS(rv, rv);
+ rv = tbDataDir->AppendNative(tbDataLeafName);
+ NS_ENSURE_SUCCESS(rv, rv);
+ }
+#endif
+
+#elif defined(ANDROID)
+ // Tor Browser Android stores data in the app home directory.
+ const char* homeDir = getenv("HOME");
+ if (!homeDir || !*homeDir)
+ return NS_ERROR_FAILURE;
+ nsresult rv = NS_NewNativeLocalFile(nsDependentCString(homeDir), true,
+ getter_AddRefs(tbDataDir));
+#else
+ // User data is embedded within the application directory (i.e.,
+ // TOR_BROWSER_DATA_OUTSIDE_APP_DIR is not defined).
+ nsresult rv = GetAppRootDir(aExeFile, getter_AddRefs(tbDataDir));
+ NS_ENSURE_SUCCESS(rv, rv);
+ rv = tbDataDir->AppendNative(NS_LITERAL_CSTRING("TorBrowser"));
+ NS_ENSURE_SUCCESS(rv, rv);
+#endif
+
+ tbDataDir.forget(aFile);
+ return NS_OK;
+}
+
+static nsresult
+GetAppRootDir(nsIFile *aExeFile, nsIFile** aFile)
+{
+ NS_ENSURE_ARG_POINTER(aExeFile);
+ NS_ENSURE_ARG_POINTER(aFile);
+ nsCOMPtr<nsIFile> appRootDir = aExeFile;
+
+ int levelsToRemove = 1; // Remove firefox (the executable file).
+#if defined(XP_MACOSX)
+ levelsToRemove += 2; // On Mac OS, we must also remove Contents/MacOS.
+#endif
+ while (appRootDir && (levelsToRemove > 0)) {
+ // When crawling up the hierarchy, components named "." do not count.
+ nsAutoCString removedName;
+ nsresult rv = appRootDir->GetNativeLeafName(removedName);
+ NS_ENSURE_SUCCESS(rv, rv);
+ bool didRemove = !removedName.Equals(".");
+
+ // Remove a directory component.
+ nsCOMPtr<nsIFile> parentDir;
+ rv = appRootDir->GetParent(getter_AddRefs(parentDir));
+ NS_ENSURE_SUCCESS(rv, rv);
+ appRootDir = parentDir;
+
+ if (didRemove)
+ --levelsToRemove;
+ }
+
+ if (!appRootDir)
+ return NS_ERROR_FAILURE;
+
+ appRootDir.forget(aFile);
+ return NS_OK;
+}
diff --git a/xpcom/io/TorFileUtils.h b/xpcom/io/TorFileUtils.h
new file mode 100644
index 000000000000..d5e86abf9685
--- /dev/null
+++ b/xpcom/io/TorFileUtils.h
@@ -0,0 +1,33 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * 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/. */
+
+#ifndef TorFileUtils_h__
+#define TorFileUtils_h__
+
+#include "nsIFile.h"
+
+/**
+ * TorBrowser_GetUserDataDir
+ *
+ * Retrieve the Tor Browser user data directory.
+ * When built with --enable-tor-browser-data-outside-app-dir, the directory
+ * is next to the application directory, except on Mac OS where it may be
+ * there or it may be at ~/Library/Application Support/TorBrowser-Data (the
+ * latter location is used if the .app bundle is in a directory whose path
+ * contains /Applications or if we lack write access to the directory that
+ * contains the .app).
+ * When built without --enable-tor-browser-data-outside-app-dir, this
+ * directory is TorBrowser.app/TorBrowser.
+ *
+ * @param aExeFile The firefox executable.
+ * @param aFile Out parameter that is set to the Tor Browser user data
+ * directory.
+ * @return NS_OK on success. Error otherwise.
+ */
+extern nsresult
+TorBrowser_GetUserDataDir(nsIFile *aExeFile, nsIFile** aFile);
+
+#endif // !TorFileUtils_h__
diff --git a/xpcom/io/moz.build b/xpcom/io/moz.build
index a165b491bc56..b0eb74f4c56d 100644
--- a/xpcom/io/moz.build
+++ b/xpcom/io/moz.build
@@ -86,6 +86,7 @@ EXPORTS += [
'nsUnicharInputStream.h',
'nsWildCard.h',
'SpecialSystemDirectory.h',
+ 'TorFileUtils.h',
]
EXPORTS.mozilla += [
@@ -135,6 +136,10 @@ UNIFIED_SOURCES += [
'SpecialSystemDirectory.cpp',
]
+SOURCES += [
+ 'TorFileUtils.cpp',
+]
+
if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'cocoa':
SOURCES += [
'CocoaFileUtils.mm',
diff --git a/xpcom/io/nsAppFileLocationProvider.cpp b/xpcom/io/nsAppFileLocationProvider.cpp
index 81551a8e3893..9f95e5cbec2d 100644
--- a/xpcom/io/nsAppFileLocationProvider.cpp
+++ b/xpcom/io/nsAppFileLocationProvider.cpp
@@ -28,6 +28,8 @@
# include <sys/param.h>
#endif
+#include "TorFileUtils.h"
+
// WARNING: These hard coded names need to go away. They need to
// come from localizable resources
@@ -234,8 +236,14 @@ nsresult nsAppFileLocationProvider::CloneMozBinDirectory(nsIFile** aLocalFile) {
// GetProductDirectory - Gets the directory which contains the application data
// folder
//
+#ifdef TOR_BROWSER_DATA_OUTSIDE_APP_DIR
+// UNIX and WIN : <App Folder>/../TorBrowser-Data/Browser
+// Mac : <App Folder>/../../../TorBrowser-Data/Browser OR
+// ~/Library/Application Support/TorBrowser-Data/Browser
+#else
// UNIX and WIN : <App Folder>/TorBrowser/Data/Browser
// Mac : <App Folder>/../../TorBrowser/Data/Browser
+#endif
//----------------------------------------------------------------------------------------
nsresult nsAppFileLocationProvider::GetProductDirectory(nsIFile** aLocalFile,
bool aLocal) {
@@ -243,42 +251,25 @@ nsresult nsAppFileLocationProvider::GetProductDirectory(nsIFile** aLocalFile,
return NS_ERROR_INVALID_ARG;
}
- nsresult rv;
+ nsresult rv = NS_ERROR_UNEXPECTED;
bool exists;
- nsCOMPtr<nsIFile> localDir;
+ nsCOMPtr<nsIFile> localDir, exeFile;
- rv = CloneMozBinDirectory(getter_AddRefs(localDir));
+ nsCOMPtr<nsIProperties> directoryService(
+ do_GetService(NS_DIRECTORY_SERVICE_CONTRACTID, &rv));
+ NS_ENSURE_SUCCESS(rv, rv);
+ rv = directoryService->Get(XRE_EXECUTABLE_FILE, NS_GET_IID(nsIFile),
+ getter_AddRefs(exeFile));
+ NS_ENSURE_SUCCESS(rv, rv);
+ rv = TorBrowser_GetUserDataDir(exeFile, getter_AddRefs(localDir));
NS_ENSURE_SUCCESS(rv, rv);
- int levelsToRemove = 1; // In FF21+, bin dir points to browser subdirectory.
-#if defined(XP_MACOSX)
- levelsToRemove += 2;
-#endif
- while (localDir && (levelsToRemove > 0)) {
- // When crawling up the hierarchy, components named "." do not count.
- nsAutoCString removedName;
- rv = localDir->GetNativeLeafName(removedName);
- NS_ENSURE_SUCCESS(rv, rv);
- bool didRemove = !removedName.Equals(".");
-
- // Remove a directory component.
- nsCOMPtr<nsIFile> parentDir;
- rv = localDir->GetParent(getter_AddRefs(parentDir));
- NS_ENSURE_SUCCESS(rv, rv);
- localDir = parentDir;
-
- if (didRemove) {
- --levelsToRemove;
- }
- }
-
- if (!localDir) {
- return NS_ERROR_FAILURE;
- }
-
+#ifdef TOR_BROWSER_DATA_OUTSIDE_APP_DIR
+ rv = localDir->AppendNative(NS_LITERAL_CSTRING("Browser"));
+#else
rv = localDir->AppendRelativeNativePath(
- NS_LITERAL_CSTRING("TorBrowser" XPCOM_FILE_PATH_SEPARATOR
- "Data" XPCOM_FILE_PATH_SEPARATOR "Browser"));
+ NS_LITERAL_CSTRING("Data" XPCOM_FILE_PATH_SEPARATOR "Browser"));
+#endif
NS_ENSURE_SUCCESS(rv, rv);
if (aLocal) {
1
0
[tor-browser/tor-browser-78.12.0esr-11.0-1] Bug 16620: Clear window.name when no referrer sent
by boklm@torproject.org 14 Jul '21
by boklm@torproject.org 14 Jul '21
14 Jul '21
commit 27396fa15161ed0ed8fd14577aa6f5708200d1a0
Author: Kathy Brade <brade(a)pearlcrescent.com>
Date: Fri Oct 30 14:28:13 2015 -0400
Bug 16620: Clear window.name when no referrer sent
Convert JS implementation (within Torbutton) to a C++ browser patch.
---
docshell/base/nsDocShell.cpp | 60 +++++++
docshell/test/mochitest/mochitest.ini | 3 +
docshell/test/mochitest/test_tor_bug16620.html | 211 +++++++++++++++++++++++++
docshell/test/mochitest/tor_bug16620.html | 51 ++++++
docshell/test/mochitest/tor_bug16620_form.html | 51 ++++++
5 files changed, 376 insertions(+)
diff --git a/docshell/base/nsDocShell.cpp b/docshell/base/nsDocShell.cpp
index d0aa79344605..22eb5c4556f6 100644
--- a/docshell/base/nsDocShell.cpp
+++ b/docshell/base/nsDocShell.cpp
@@ -7476,11 +7476,71 @@ nsresult nsDocShell::CreateContentViewer(const nsACString& aContentType,
aOpenedChannel->GetURI(getter_AddRefs(mLoadingURI));
}
FirePageHideNotification(!mSavingOldViewer);
+
if (mIsBeingDestroyed) {
// Force to stop the newly created orphaned viewer.
viewer->Stop();
return NS_ERROR_DOCSHELL_DYING;
}
+
+ // Tor bug 16620: Clear window.name of top-level documents if
+ // there is no referrer. We make an exception for new windows,
+ // e.g., window.open(url, "MyName").
+ bool isNewWindowTarget = false;
+ nsCOMPtr<nsIPropertyBag2> props(do_QueryInterface(aRequest, &rv));
+ if (props) {
+ props->GetPropertyAsBool(NS_LITERAL_STRING("docshell.newWindowTarget"),
+ &isNewWindowTarget);
+ }
+
+ if (!isNewWindowTarget) {
+ nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(aOpenedChannel));
+ nsCOMPtr<nsIURI> httpReferrer;
+ if (httpChannel) {
+ nsCOMPtr<nsIReferrerInfo> referrerInfo;
+ rv = httpChannel->GetReferrerInfo(getter_AddRefs(referrerInfo));
+ NS_ENSURE_SUCCESS(rv, rv);
+ if (referrerInfo) {
+ // We want GetComputedReferrer() instead of GetOriginalReferrer(), since
+ // the former takes into consideration referrer policy, protocol
+ // whitelisting...
+ httpReferrer = referrerInfo->GetComputedReferrer();
+ }
+ }
+
+ bool isTopFrame = mBrowsingContext->IsTop();
+
+#ifdef DEBUG_WINDOW_NAME
+ printf("DOCSHELL %p CreateContentViewer - possibly clearing window.name:\n",
+ this);
+ printf(" current window.name: \"%s\"\n",
+ NS_ConvertUTF16toUTF8(mName).get());
+
+ nsAutoCString curSpec, loadingSpec;
+ if (this->mCurrentURI) mCurrentURI->GetSpec(curSpec);
+ if (mLoadingURI) mLoadingURI->GetSpec(loadingSpec);
+ printf(" current URI: %s\n", curSpec.get());
+ printf(" loading URI: %s\n", loadingSpec.get());
+ printf(" is top document: %s\n", isTopFrame ? "Yes" : "No");
+
+ if (!httpReferrer) {
+ printf(" referrer: None\n");
+ } else {
+ nsAutoCString refSpec;
+ httpReferrer->GetSpec(refSpec);
+ printf(" referrer: %s\n", refSpec.get());
+ }
+#endif
+
+ bool clearName = isTopFrame && !httpReferrer;
+ if (clearName) SetName(NS_LITERAL_STRING(""));
+
+#ifdef DEBUG_WINDOW_NAME
+ printf(" action taken: %s window.name\n",
+ clearName ? "Cleared" : "Preserved");
+#endif
+ }
+
mLoadingURI = nullptr;
// Set mFiredUnloadEvent = false so that the unload handler for the
diff --git a/docshell/test/mochitest/mochitest.ini b/docshell/test/mochitest/mochitest.ini
index 25d3187711fe..663750b7fc8e 100644
--- a/docshell/test/mochitest/mochitest.ini
+++ b/docshell/test/mochitest/mochitest.ini
@@ -52,6 +52,8 @@ support-files =
start_historyframe.html
url1_historyframe.html
url2_historyframe.html
+ tor_bug16620.html
+ tor_bug16620_form.html
[test_anchor_scroll_after_document_open.html]
[test_bfcache_plus_hash.html]
@@ -115,6 +117,7 @@ support-files = file_bug675587.html
[test_framedhistoryframes.html]
support-files = file_framedhistoryframes.html
[test_pushState_after_document_open.html]
+[test_tor_bug16620.html]
[test_windowedhistoryframes.html]
[test_triggeringprincipal_location_seturi.html]
[test_bug1507702.html]
diff --git a/docshell/test/mochitest/test_tor_bug16620.html b/docshell/test/mochitest/test_tor_bug16620.html
new file mode 100644
index 000000000000..46fff5a04711
--- /dev/null
+++ b/docshell/test/mochitest/test_tor_bug16620.html
@@ -0,0 +1,211 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+ Tor Bug 16620: Clear window.name when no referrer sent.
+ https://trac.torproject.org/projects/tor/ticket/16620
+-->
+<meta charset="utf-8">
+<head>
+ <title>Test for Tor Bug 16620 - Clear window.name when no referrer sent</title>
+ <script type="application/javascript"
+ src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://trac.torproject.org/projects/tor/ticket/16620">Tor Bug 16620</a>
+<script>
+// ## Test constants
+const kTestPath = "/tests/docshell/test/mochitest/";
+const kLinkFile = "tor_bug16620.html";
+const kFormFile = "tor_bug16620_form.html";
+const kBaseURL1 = "http://example.com";
+const kBaseURL1_https = "https://example.com";
+const kBaseURL2 = "http://example.net";
+const kSendReferrerPref = "network.http.sendRefererHeader";
+const kSendReferrerNever = 0;
+const kSendReferrerForUserAction = 1;
+const kSendReferrerAlways = 2;
+
+let gTests = [
+ // Test #1: Same domain; never send referrer.
+ { startURL: kBaseURL1, destURL: kBaseURL1,
+ referrerPref: kSendReferrerNever,
+ expectIsolation: true },
+
+ // Test #2: Same domain; send referrer upon user action.
+ { startURL: kBaseURL1, destURL: kBaseURL1,
+ referrerPref: kSendReferrerForUserAction,
+ expectIsolation: false },
+
+ // Test #3: Same domain; always send referrer.
+ { startURL: kBaseURL1, destURL: kBaseURL1,
+ referrerPref: kSendReferrerAlways,
+ expectIsolation: false },
+
+ // Test #4: Different top-level domains; never send referrer.
+ { startURL: kBaseURL1, destURL: kBaseURL2,
+ referrerPref: kSendReferrerNever,
+ expectIsolation: true },
+
+ // Test #5: Different top-level domains; send referrer upon user action.
+ { startURL: kBaseURL1, destURL: kBaseURL2,
+ referrerPref: kSendReferrerForUserAction,
+ expectIsolation: false },
+
+ // Test #6: Different top-level domains; always send referrer.
+ { startURL: kBaseURL1, destURL: kBaseURL2,
+ referrerPref: kSendReferrerAlways,
+ expectIsolation: false },
+
+ // Test #7: https -> http transition.
+ { startURL: kBaseURL1_https, destURL: kBaseURL1,
+ referrerPref: kSendReferrerForUserAction,
+ expectIsolation: true },
+
+ // Test #8: Same domain, rel="noreferrer" on link.
+ { startURL: kBaseURL1, destURL: kBaseURL1, noReferrerOnLink: true,
+ referrerPref: kSendReferrerAlways,
+ expectIsolation: true },
+
+ // Test #9: Same domain, "no-referrer" meta tag in document.
+ { startURL: kBaseURL1, destURL: kBaseURL1, noReferrerInMetaTag: true,
+ referrerPref: kSendReferrerAlways,
+ expectIsolation: true },
+
+ // Test #10: Like test #9, but reset window.name during unload.
+ // (similar to http://www.thomasfrank.se/sessvarsTestPage1.html)
+ { startURL: kBaseURL1, destURL: kBaseURL1, noReferrerInMetaTag: true,
+ resetInUnload: true,
+ referrerPref: kSendReferrerAlways,
+ expectIsolation: true },
+
+ // Test #11: Data URL as destination (no referrer).
+ { startURL: kBaseURL1,
+ referrerPref: kSendReferrerAlways,
+ expectIsolation: true },
+
+ // Test #12: Ensure that window.name is preserved when a dynamically loaded
+ // iframe is used to perform a form post (regression test for Tor bug 18168).
+ { startURL: kBaseURL1,
+ isFormTest: true,
+ referrerPref: kSendReferrerAlways,
+ expectIsolation: false },
+];
+
+let gCurTest = 0;
+let gCurWinName, gChildWin, gDataURL;
+
+// ## Utility functions
+function generateRandomName()
+{
+ // Generate a random 6 character string using 0-9 and a-z.
+ return ((1 + Math.random()).toString(36) + '000000').substr(2, 6);
+}
+
+function startNextTest() {
+ ++gCurTest;
+ if (gCurTest > gTests.length) {
+ SimpleTest.finish();
+ } else {
+ let curTest = gTests[gCurTest - 1];
+ if ("referrerPref" in curTest)
+ SpecialPowers.setIntPref(kSendReferrerPref, curTest.referrerPref);
+ else
+ SpecialPowers.setIntPref(kSendReferrerPref, kSendReferrerForUserAction);
+ gCurWinName = generateRandomName();
+ let url = curTest.startURL + kTestPath;
+ if (curTest.isFormTest === true) {
+ url += kFormFile + "?" + gCurWinName;
+ gChildWin = window.open(url, undefined);
+ } else {
+ url += kLinkFile + "?firstDocLoaded";
+ gChildWin = window.open(url, gCurWinName);
+ }
+ }
+}
+
+// ## Add a message event listener.
+window.addEventListener("message", function(aEvent) {
+ if (aEvent.source !== gChildWin)
+ return;
+
+// console.log("parent received message:" + JSON.stringify(aEvent.data));
+
+ let proceedToNextTest = false;
+ let curTest = gTests[gCurTest - 1];
+ let state = aEvent.data.state;
+ let winName = aEvent.data.winName;
+ if ("firstDocLoaded" == state) {
+ // Process response from step one of the link-based tests.
+ let step1Passed = (winName === gCurWinName);
+ if (!step1Passed) {
+ ok(step1Passed, "Test #" + gCurTest +
+ " - first document's name matches window.open parameter");
+ proceedToNextTest = true;
+ }
+
+ // Send an "openURL" message to the loaded document.
+ let url2 = (curTest.destURL)
+ ? curTest.destURL + kTestPath + kLinkFile + "?secondDocLoaded"
+ : gDataURL;
+ let noReferrerOnLink = (curTest.noReferrerOnLink === true);
+ let noReferrerInMetaTag = (curTest.noReferrerInMetaTag === true);
+ let resetInUnload = (curTest.resetInUnload === true);
+ aEvent.source.postMessage({ action: "openURL", url: url2,
+ noReferrerOnLink: noReferrerOnLink,
+ noReferrerInMetaTag: noReferrerInMetaTag,
+ resetInUnload: resetInUnload },
+ "*");
+ } else if ("secondDocLoaded" == state) {
+ // Process response from step two of the link-based tests.
+ if (curTest.expectIsolation) {
+ ok(winName === "",
+ "Test #" + gCurTest + " - second document: name was cleared");
+ } else {
+ ok(winName === gCurWinName,
+ "Test #" + gCurTest + " - second document: name was preserved");
+ }
+ proceedToNextTest = true;
+ } else if ("formPostDone" == state) {
+ // Process response from the form post tests.
+ if (curTest.expectIsolation) {
+ ok(winName === "",
+ "Test #" + gCurTest + " - iframe form post: name was cleared");
+ } else {
+ ok(winName === gCurWinName,
+ "Test #" + gCurTest + " - iframe form post: name was preserved");
+ }
+ proceedToNextTest = true;
+
+ }
+
+ if (proceedToNextTest) {
+ gChildWin.close();
+ startNextTest();
+ }
+ }, false);
+
+ SimpleTest.waitForExplicitFinish();
+
+ if (SpecialPowers.getBoolPref("security.nocertdb")) {
+ // Mochitests don't simulate https correctly with "security.nocertdb"
+ // enabled. See https://bugs.torproject.org/18087
+ ok(false, "Please disable the pref `security.nocertdb` before running this test.");
+ SimpleTest.finish();
+ } else {
+
+ // Read file contents, construct a data URL (used by some tests), and
+ // then start the first test.
+ let url = kTestPath + kLinkFile;
+ let xhr = new XMLHttpRequest();
+ xhr.open("GET", url);
+ xhr.onload = function() {
+ gDataURL = "data:text/html;charset=utf-8,"
+ + encodeURIComponent(this.responseText);
+ startNextTest();
+ }
+ xhr.send();
+ }
+</script>
+</body>
+</html>
diff --git a/docshell/test/mochitest/tor_bug16620.html b/docshell/test/mochitest/tor_bug16620.html
new file mode 100644
index 000000000000..26b8e406bbff
--- /dev/null
+++ b/docshell/test/mochitest/tor_bug16620.html
@@ -0,0 +1,51 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+ Tor Bug 16620: Clear window.name when no referrer sent.
+ https://trac.torproject.org/projects/tor/ticket/16620
+-->
+<head>
+ <meta charset="UTF-8">
+ <title>Supporting Doc for Tor Bug 16620 Tests</title>
+</head>
+<body>
+<a id="link" href="">secondDoc</a>
+
+<script>
+// Extract test state from our query string, defaulting to
+// "secondDocLoaded" to support use of this HTML content within
+// a data URI (where query strings are not supported).
+let state = (location.search.length > 0) ? location.search.substr(1)
+ : "secondDocLoaded";
+
+// Notify the test driver.
+opener.postMessage({ state: state, winName: window.name }, "*");
+
+// Add a message event listener to process "openURL" actions.
+window.addEventListener("message", function(aEvent) {
+ if (aEvent.data.action == "openURL") {
+ if (aEvent.data.noReferrerInMetaTag) {
+ let metaElem = document.createElement("meta");
+ metaElem.name = "referrer";
+ metaElem.content = "no-referrer";
+ document.head.appendChild(metaElem);
+ }
+
+ let linkElem = document.getElementById("link");
+ linkElem.href = aEvent.data.url;
+ if (aEvent.data.noReferrerOnLink)
+ linkElem.rel = "noreferrer";
+
+ if (aEvent.data.resetInUnload) {
+ let tmpName = window.name;
+ window.addEventListener("unload", function() {
+ window.name = tmpName;
+ }, false);
+ }
+
+ linkElem.click();
+ }
+}, false);
+</script>
+</body>
+</html>
diff --git a/docshell/test/mochitest/tor_bug16620_form.html b/docshell/test/mochitest/tor_bug16620_form.html
new file mode 100644
index 000000000000..279f62e63fab
--- /dev/null
+++ b/docshell/test/mochitest/tor_bug16620_form.html
@@ -0,0 +1,51 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+ Tor Bug 16620: Clear window.name when no referrer sent.
+ https://trac.torproject.org/projects/tor/ticket/16620
+
+ Regression test for bug 18168: iframe-based AJAX call opening in new tab
+-->
+<head>
+ <meta charset="UTF-8">
+ <title>Supporting Form-based Doc for Tor Bug 16620 Tests</title>
+</head>
+<body>
+
+<script>
+document.addEventListener("DOMContentLoaded", function () {
+ addPostTarget();
+}, false);
+
+
+function addPostTarget()
+{
+ let frameName = location.search.substr(1);
+ let form = document.getElementById("postform");
+ let iframe = document.createElement("iframe");
+ iframe.style.border = "1px solid red";
+ iframe.src = "about:blank";
+ form.target = iframe.name = iframe.id = frameName;
+ document.body.appendChild(iframe);
+
+ let didSubmit = false;
+ iframe.onload = function() {
+ if (!didSubmit) {
+ didSubmit = true;
+ let submitButton = document.getElementById("submitButton");
+ submitButton.click();
+ } else {
+ // Form submission complete. Report iframe's name to test driver.
+ opener.postMessage({ state: "formPostDone", winName: iframe.name }, "*");
+ }
+ };
+}
+
+</script>
+<form name="postform" id="postform"
+ action="data:text/plain;charset=utf-8,Hello%20world"
+ method="POST" enctype="multipart/form-data">
+ <input type="hidden" name="field1" value="value1"><br>
+ <input id="submitButton" type="submit" value="Post It">
+</body>
+</html>
1
0
[tor-browser/tor-browser-78.12.0esr-11.0-1] Bug 19273: Avoid JavaScript patching of the external app helper dialog.
by boklm@torproject.org 14 Jul '21
by boklm@torproject.org 14 Jul '21
14 Jul '21
commit 1fa8ac7f02880e8353908efae11b8a071d2ebd0b
Author: Kathy Brade <brade(a)pearlcrescent.com>
Date: Tue Jun 28 15:13:05 2016 -0400
Bug 19273: Avoid JavaScript patching of the external app helper dialog.
When handling an external URI or downloading a file, invoke Torbutton's
external app blocker component (which will present a download warning
dialog unless the user has checked the "Automatically download files
from now on" box).
For e10s compatibility, avoid using a modal dialog and instead use
a callback interface (nsIHelperAppWarningLauncher) to allow Torbutton
to indicate the user's desire to cancel or continue each request.
Other bugs fixed:
Bug 21766: Crash with e10s enabled while trying to download a file
Bug 21886: Download is stalled in non-e10s mode
Bug 22471: Downloading files via the PDF viewer download button is broken
Bug 22472: Fix FTP downloads when external helper app dialog is shown
Bug 22610: Avoid crashes when canceling external helper app downloads
Bug 22618: Downloading pdf file via file:/// is stalling
---
.../exthandler/nsExternalHelperAppService.cpp | 202 +++++++++++++++++----
uriloader/exthandler/nsExternalHelperAppService.h | 3 +
.../exthandler/nsIExternalHelperAppService.idl | 47 +++++
3 files changed, 217 insertions(+), 35 deletions(-)
diff --git a/uriloader/exthandler/nsExternalHelperAppService.cpp b/uriloader/exthandler/nsExternalHelperAppService.cpp
index 4ff7ed2e27cc..0dcc1d3ed6ab 100644
--- a/uriloader/exthandler/nsExternalHelperAppService.cpp
+++ b/uriloader/exthandler/nsExternalHelperAppService.cpp
@@ -132,6 +132,9 @@ static const char NEVER_ASK_FOR_SAVE_TO_DISK_PREF[] =
static const char NEVER_ASK_FOR_OPEN_FILE_PREF[] =
"browser.helperApps.neverAsk.openFile";
+static const char WARNING_DIALOG_CONTRACT_ID[] =
+ "@torproject.org/torbutton-extAppBlocker;1";
+
// Helper functions for Content-Disposition headers
/**
@@ -388,6 +391,22 @@ static nsresult GetDownloadDirectory(nsIFile** _directory,
return NS_OK;
}
+static already_AddRefed<nsIInterfaceRequestor> GetDialogParentAux(
+ BrowsingContext* aBrowsingContext, nsIInterfaceRequestor* aWindowContext) {
+ nsCOMPtr<nsIInterfaceRequestor> dialogParent = aWindowContext;
+
+ if (!dialogParent && aBrowsingContext) {
+ dialogParent = do_QueryInterface(aBrowsingContext->GetDOMWindow());
+ }
+ if (!dialogParent && aBrowsingContext && XRE_IsParentProcess()) {
+ RefPtr<Element> element = aBrowsingContext->Top()->GetEmbedderElement();
+ if (element) {
+ dialogParent = do_QueryInterface(element->OwnerDoc()->GetWindow());
+ }
+ }
+ return dialogParent.forget();
+}
+
/**
* Structure for storing extension->type mappings.
* @see defaultMimeEntries
@@ -544,6 +563,111 @@ static const nsDefaultMimeTypeEntry nonDecodableExtensions[] = {
{APPLICATION_COMPRESS, "z"},
{APPLICATION_GZIP, "svgz"}};
+//////////////////////////////////////////////////////////////////////////////////////////////////////
+// begin nsExternalLoadURIHandler class definition and implementation
+//////////////////////////////////////////////////////////////////////////////////////////////////////
+class nsExternalLoadURIHandler final : public nsIHelperAppWarningLauncher {
+ public:
+ NS_DECL_THREADSAFE_ISUPPORTS
+ NS_DECL_NSIHELPERAPPWARNINGLAUNCHER
+
+ nsExternalLoadURIHandler(nsIHandlerInfo* aHandlerInfo, nsIURI* aURI,
+ nsIPrincipal* aTriggeringPrincipal,
+ BrowsingContext* aBrowsingContext);
+
+ protected:
+ ~nsExternalLoadURIHandler();
+
+ nsCOMPtr<nsIHandlerInfo> mHandlerInfo;
+ nsCOMPtr<nsIURI> mURI;
+ nsCOMPtr<nsIPrincipal> mTriggeringPrincipal;
+ RefPtr<BrowsingContext> mBrowsingContext;
+ nsCOMPtr<nsIHelperAppWarningDialog> mWarningDialog;
+};
+
+NS_IMPL_ADDREF(nsExternalLoadURIHandler)
+NS_IMPL_RELEASE(nsExternalLoadURIHandler)
+
+NS_INTERFACE_MAP_BEGIN(nsExternalLoadURIHandler)
+ NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIHelperAppWarningLauncher)
+ NS_INTERFACE_MAP_ENTRY(nsIHelperAppWarningLauncher)
+NS_INTERFACE_MAP_END
+
+nsExternalLoadURIHandler::nsExternalLoadURIHandler(
+ nsIHandlerInfo* aHandlerInfo, nsIURI* aURI,
+ nsIPrincipal* aTriggeringPrincipal, BrowsingContext* aBrowsingContext)
+ : mHandlerInfo(aHandlerInfo),
+ mURI(aURI),
+ mTriggeringPrincipal(aTriggeringPrincipal),
+ mBrowsingContext(aBrowsingContext)
+
+{
+ nsresult rv = NS_OK;
+ mWarningDialog = do_CreateInstance(WARNING_DIALOG_CONTRACT_ID, &rv);
+ if (NS_SUCCEEDED(rv) && mWarningDialog) {
+ // This will create a reference cycle (the dialog holds a reference to us
+ // as nsIHelperAppWarningLauncher), which will be broken in ContinueRequest
+ // or CancelRequest.
+ nsCOMPtr<nsIInterfaceRequestor> dialogParent =
+ GetDialogParentAux(aBrowsingContext, nullptr);
+ rv = mWarningDialog->MaybeShow(this, dialogParent);
+ }
+
+ if (NS_FAILED(rv)) {
+ // If for some reason we could not open the download warning prompt,
+ // continue with the request.
+ ContinueRequest();
+ }
+}
+
+nsExternalLoadURIHandler::~nsExternalLoadURIHandler() {}
+
+NS_IMETHODIMP nsExternalLoadURIHandler::ContinueRequest() {
+ MOZ_ASSERT(mURI);
+ MOZ_ASSERT(mHandlerInfo);
+
+ // Break our reference cycle with the download warning dialog (set up in
+ // LoadURI).
+ mWarningDialog = nullptr;
+
+ nsHandlerInfoAction preferredAction;
+ mHandlerInfo->GetPreferredAction(&preferredAction);
+ bool alwaysAsk = true;
+ mHandlerInfo->GetAlwaysAskBeforeHandling(&alwaysAsk);
+
+ nsresult rv = NS_OK;
+ // If we are not supposed to ask, and the preferred action is to use
+ // a helper app or the system default, we just launch the URI.
+ if (!alwaysAsk && (preferredAction == nsIHandlerInfo::useHelperApp ||
+ preferredAction == nsIHandlerInfo::useSystemDefault)) {
+ rv = mHandlerInfo->LaunchWithURI(mURI, mBrowsingContext);
+ // We are not supposed to ask, but when file not found the user most likely
+ // uninstalled the application which handles the uri so we will continue
+ // by application chooser dialog.
+ if (rv != NS_ERROR_FILE_NOT_FOUND) {
+ return rv;
+ }
+ }
+
+ nsCOMPtr<nsIContentDispatchChooser> chooser =
+ do_CreateInstance("@mozilla.org/content-dispatch-chooser;1", &rv);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ return chooser->Ask(mHandlerInfo, mURI, mTriggeringPrincipal,
+ mBrowsingContext,
+ nsIContentDispatchChooser::REASON_CANNOT_HANDLE);
+}
+
+NS_IMETHODIMP nsExternalLoadURIHandler::CancelRequest(nsresult aReason) {
+ NS_ENSURE_ARG(NS_FAILED(aReason));
+
+ // Break our reference cycle with the download warning dialog (set up in
+ // LoadURI).
+ mWarningDialog = nullptr;
+
+ return NS_OK;
+}
+
static StaticRefPtr<nsExternalHelperAppService> sExtHelperAppSvcSingleton;
/**
@@ -570,6 +694,9 @@ nsExternalHelperAppService::GetSingleton() {
return do_AddRef(sExtHelperAppSvcSingleton);
}
+//////////////////////////////////////////////////////////////////////////////////////////////////////
+// nsExternalHelperAppService definition and implementation
+//////////////////////////////////////////////////////////////////////////////////////////////////////
NS_IMPL_ISUPPORTS(nsExternalHelperAppService, nsIExternalHelperAppService,
nsPIExternalAppLauncher, nsIExternalProtocolService,
nsIMIMEService, nsIObserver, nsISupportsWeakReference)
@@ -1003,30 +1130,13 @@ nsExternalHelperAppService::LoadURI(nsIURI* aURI,
rv = GetProtocolHandlerInfo(scheme, getter_AddRefs(handler));
NS_ENSURE_SUCCESS(rv, rv);
- nsHandlerInfoAction preferredAction;
- handler->GetPreferredAction(&preferredAction);
- bool alwaysAsk = true;
- handler->GetAlwaysAskBeforeHandling(&alwaysAsk);
-
- // if we are not supposed to ask, and the preferred action is to use
- // a helper app or the system default, we just launch the URI.
- if (!alwaysAsk && (preferredAction == nsIHandlerInfo::useHelperApp ||
- preferredAction == nsIHandlerInfo::useSystemDefault)) {
- rv = handler->LaunchWithURI(uri, aBrowsingContext);
- // We are not supposed to ask, but when file not found the user most likely
- // uninstalled the application which handles the uri so we will continue
- // by application chooser dialog.
- if (rv != NS_ERROR_FILE_NOT_FOUND) {
- return rv;
- }
+ RefPtr<nsExternalLoadURIHandler> h = new nsExternalLoadURIHandler(
+ handler, uri, aTriggeringPrincipal, aBrowsingContext);
+ if (!h) {
+ return NS_ERROR_OUT_OF_MEMORY;
}
- nsCOMPtr<nsIContentDispatchChooser> chooser =
- do_CreateInstance("@mozilla.org/content-dispatch-chooser;1", &rv);
- NS_ENSURE_SUCCESS(rv, rv);
-
- return chooser->Ask(handler, uri, aTriggeringPrincipal, aBrowsingContext,
- nsIContentDispatchChooser::REASON_CANNOT_HANDLE);
+ return NS_OK;
}
//////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -1171,6 +1281,7 @@ NS_INTERFACE_MAP_BEGIN(nsExternalAppHandler)
NS_INTERFACE_MAP_ENTRY(nsIStreamListener)
NS_INTERFACE_MAP_ENTRY(nsIRequestObserver)
NS_INTERFACE_MAP_ENTRY(nsIHelperAppLauncher)
+ NS_INTERFACE_MAP_ENTRY(nsIHelperAppWarningLauncher)
NS_INTERFACE_MAP_ENTRY(nsICancelable)
NS_INTERFACE_MAP_ENTRY(nsIBackgroundFileSaverObserver)
NS_INTERFACE_MAP_ENTRY(nsINamed)
@@ -1532,18 +1643,7 @@ void nsExternalAppHandler::MaybeApplyDecodingForExtension(
already_AddRefed<nsIInterfaceRequestor>
nsExternalAppHandler::GetDialogParent() {
- nsCOMPtr<nsIInterfaceRequestor> dialogParent = mWindowContext;
-
- if (!dialogParent && mBrowsingContext) {
- dialogParent = do_QueryInterface(mBrowsingContext->GetDOMWindow());
- }
- if (!dialogParent && mBrowsingContext && XRE_IsParentProcess()) {
- RefPtr<Element> element = mBrowsingContext->Top()->GetEmbedderElement();
- if (element) {
- dialogParent = do_QueryInterface(element->OwnerDoc()->GetWindow());
- }
- }
- return dialogParent.forget();
+ return GetDialogParentAux(mBrowsingContext, mWindowContext);
}
NS_IMETHODIMP nsExternalAppHandler::OnStartRequest(nsIRequest* request) {
@@ -1651,6 +1751,29 @@ NS_IMETHODIMP nsExternalAppHandler::OnStartRequest(nsIRequest* request) {
MOZ_ASSERT(NS_SUCCEEDED(rv));
}
+ mWarningDialog = do_CreateInstance(WARNING_DIALOG_CONTRACT_ID, &rv);
+ if (NS_SUCCEEDED(rv) && mWarningDialog) {
+ // This will create a reference cycle (the dialog holds a reference to us
+ // as nsIHelperAppWarningLauncher), which will be broken in ContinueRequest
+ // or CancelRequest.
+ nsCOMPtr<nsIInterfaceRequestor> dialogParent = GetDialogParent();
+ rv = mWarningDialog->MaybeShow(this, dialogParent);
+ }
+
+ if (NS_FAILED(rv)) {
+ // If for some reason we could not open the download warning prompt,
+ // continue with the request.
+ ContinueRequest();
+ }
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsExternalAppHandler::ContinueRequest() {
+ // Break our reference cycle with the download warning dialog (set up in
+ // OnStartRequest).
+ mWarningDialog = nullptr;
+
// now that the temp file is set up, find out if we need to invoke a dialog
// asking the user what they want us to do with this content...
@@ -1736,6 +1859,7 @@ NS_IMETHODIMP nsExternalAppHandler::OnStartRequest(nsIRequest* request) {
action = nsIMIMEInfo::saveToDisk;
}
+ nsresult rv = NS_OK;
if (alwaysAsk) {
// Display the dialog
mDialog = do_CreateInstance(NS_HELPERAPPLAUNCHERDLG_CONTRACTID, &rv);
@@ -1793,6 +1917,14 @@ NS_IMETHODIMP nsExternalAppHandler::OnStartRequest(nsIRequest* request) {
return NS_OK;
}
+NS_IMETHODIMP nsExternalAppHandler::CancelRequest(nsresult aReason) {
+ // Break our reference cycle with the download warning dialog (set up in
+ // OnStartRequest).
+ mWarningDialog = nullptr;
+
+ return Cancel(aReason);
+}
+
// Convert error info into proper message text and send OnStatusChange
// notification to the dialog progress listener or nsITransfer implementation.
void nsExternalAppHandler::SendStatusChange(ErrorType type, nsresult rv,
@@ -2456,7 +2588,7 @@ NS_IMETHODIMP nsExternalAppHandler::Cancel(nsresult aReason) {
}
// Break our reference cycle with the helper app dialog (set up in
- // OnStartRequest)
+ // ContinueRequest)
mDialog = nullptr;
mRequest = nullptr;
diff --git a/uriloader/exthandler/nsExternalHelperAppService.h b/uriloader/exthandler/nsExternalHelperAppService.h
index f2bd67f64ccd..8c2d8817ac7b 100644
--- a/uriloader/exthandler/nsExternalHelperAppService.h
+++ b/uriloader/exthandler/nsExternalHelperAppService.h
@@ -203,6 +203,7 @@ class nsExternalHelperAppService : public nsIExternalHelperAppService,
*/
class nsExternalAppHandler final : public nsIStreamListener,
public nsIHelperAppLauncher,
+ public nsIHelperAppWarningLauncher,
public nsIBackgroundFileSaverObserver,
public nsINamed {
public:
@@ -210,6 +211,7 @@ class nsExternalAppHandler final : public nsIStreamListener,
NS_DECL_NSISTREAMLISTENER
NS_DECL_NSIREQUESTOBSERVER
NS_DECL_NSIHELPERAPPLAUNCHER
+ NS_DECL_NSIHELPERAPPWARNINGLAUNCHER
NS_DECL_NSICANCELABLE
NS_DECL_NSIBACKGROUNDFILESAVEROBSERVER
NS_DECL_NSINAMED
@@ -460,6 +462,7 @@ class nsExternalAppHandler final : public nsIStreamListener,
nsCOMPtr<nsITransfer> mTransfer;
nsCOMPtr<nsIHelperAppLauncherDialog> mDialog;
+ nsCOMPtr<nsIHelperAppWarningDialog> mWarningDialog;
/**
diff --git a/uriloader/exthandler/nsIExternalHelperAppService.idl b/uriloader/exthandler/nsIExternalHelperAppService.idl
index ea8b9b08f3e6..8b58671f7597 100644
--- a/uriloader/exthandler/nsIExternalHelperAppService.idl
+++ b/uriloader/exthandler/nsIExternalHelperAppService.idl
@@ -182,3 +182,50 @@ interface nsIHelperAppLauncher : nsICancelable
*/
readonly attribute uint64_t browsingContextId;
};
+
+/**
+ * nsIHelperAppWarningLauncher is implemented by two classes:
+ * nsExternalLoadURIHandler
+ * nsExternalAppHandler
+ */
+[scriptable, uuid(cffd508b-4aaf-43ad-99c6-671d35cbc558)]
+interface nsIHelperAppWarningLauncher : nsISupports
+{
+ /**
+ * Callback invoked by the external app warning dialog to continue the
+ * request.
+ * NOTE: This will release the reference to the nsIHelperAppWarningDialog.
+ */
+ void continueRequest();
+
+ /**
+ * Callback invoked by the external app warning dialog to cancel the request.
+ * NOTE: This will release the reference to the nsIHelperAppWarningDialog.
+ *
+ * @param aReason
+ * Pass a failure code to indicate the reason why this operation is
+ * being canceled. It is an error to pass a success code.
+ */
+ void cancelRequest(in nsresult aReason);
+};
+
+/**
+ * nsIHelperAppWarningDialog is implemented by Torbutton's external app
+ * blocker (src/components/external-app-blocker.js).
+ */
+[scriptable, uuid(f4899a3f-0df3-42cc-9db8-bdf599e5a208)]
+interface nsIHelperAppWarningDialog : nsISupports
+{
+ /**
+ * Possibly show a launch warning dialog (it will not be shown if the user
+ * has chosen to not see the warning again).
+ *
+ * @param aLauncher
+ * A nsIHelperAppWarningLauncher to be invoked after the user confirms
+ * or cancels the download.
+ * @param aWindowContext
+ * The window associated with the download.
+ */
+ void maybeShow(in nsIHelperAppWarningLauncher aLauncher,
+ in nsISupports aWindowContext);
+};
1
0
[tor-browser/tor-browser-78.12.0esr-11.0-1] Bug 18800: Remove localhost DNS lookup in nsProfileLock.cpp
by boklm@torproject.org 14 Jul '21
by boklm@torproject.org 14 Jul '21
14 Jul '21
commit 3fff4c3437ce8442abe53f43096afcda25aaa61f
Author: Kathy Brade <brade(a)pearlcrescent.com>
Date: Thu Apr 21 10:40:26 2016 -0400
Bug 18800: Remove localhost DNS lookup in nsProfileLock.cpp
Instead of using the local computer's IP address within
symlink-based profile lock signatures, always use 127.0.0.1.
---
toolkit/profile/nsProfileLock.cpp | 17 ++++++++---------
1 file changed, 8 insertions(+), 9 deletions(-)
diff --git a/toolkit/profile/nsProfileLock.cpp b/toolkit/profile/nsProfileLock.cpp
index 25c4f5a79e56..1942815e3446 100644
--- a/toolkit/profile/nsProfileLock.cpp
+++ b/toolkit/profile/nsProfileLock.cpp
@@ -289,18 +289,17 @@ nsresult nsProfileLock::LockWithSymlink(nsIFile* aLockFile,
if (!mReplacedLockTime)
aLockFile->GetLastModifiedTimeOfLink(&mReplacedLockTime);
+ // For Tor Browser, avoid a DNS lookup here so the Tor network is not
+ // bypassed. Instead, always use 127.0.0.1 for the IP address portion
+ // of the lock signature, which may cause the browser to refuse to
+ // start in the rare event that all of the following conditions are met:
+ // 1. The browser profile is on a network file system.
+ // 2. The file system does not support fcntl() locking.
+ // 3. Tor Browser is run from two different computers at the same time.
+
struct in_addr inaddr;
inaddr.s_addr = htonl(INADDR_LOOPBACK);
- char hostname[256];
- PRStatus status = PR_GetSystemInfo(PR_SI_HOSTNAME, hostname, sizeof hostname);
- if (status == PR_SUCCESS) {
- char netdbbuf[PR_NETDB_BUF_SIZE];
- PRHostEnt hostent;
- status = PR_GetHostByName(hostname, netdbbuf, sizeof netdbbuf, &hostent);
- if (status == PR_SUCCESS) memcpy(&inaddr, hostent.h_addr, sizeof inaddr);
- }
-
mozilla::SmprintfPointer signature =
mozilla::Smprintf("%s:%s%lu", inet_ntoa(inaddr),
aHaveFcntlLock ? "+" : "", (unsigned long)getpid());
1
0