henry pushed to branch tor-browser-153.0esr-16.0-1 at The Tor Project / Applications / Tor Browser
Commits:
-
34750d3a
by Henry Wilkes at 2026-07-28T13:15:52+00:00
-
1f471dc9
by Henry Wilkes at 2026-07-28T13:15:52+00:00
-
2064e1c8
by Henry Wilkes at 2026-07-28T13:15:52+00:00
-
631c2c54
by Henry Wilkes at 2026-07-28T13:15:52+00:00
-
da12add2
by Henry Wilkes at 2026-07-28T13:15:52+00:00
-
21d6cfe7
by Henry Wilkes at 2026-07-28T13:15:52+00:00
18 changed files:
- browser/components/DesktopActorRegistry.sys.mjs
- browser/components/about/AboutRedirector.cpp
- + browser/components/aboutmanual/AboutManualChild.sys.mjs
- + browser/components/aboutmanual/AboutManualParent.sys.mjs
- + browser/components/aboutmanual/content/aboutManual.js
- + browser/components/aboutmanual/jar.mn
- + browser/components/aboutmanual/moz.build
- browser/components/moz.build
- browser/components/onionservices/content/authPopup.inc.xhtml
- browser/components/preferences/config/passwords-autofill.mjs
- browser/components/preferences/letterboxing.inc.xhtml
- browser/components/securitylevel/content/securityLevelPanel.inc.xhtml
- browser/components/securitylevel/content/securityLevelPreferences.inc.xhtml
- browser/components/torpreferences/config/connection.mjs
- browser/components/torpreferences/content/connectionPane.inc.xhtml
- browser/components/torpreferences/content/provideBridgeDialog.xhtml
- toolkit/content/aboutNetError.mjs
- toolkit/modules/TorStrings.sys.mjs
Changes:
| ... | ... | @@ -126,6 +126,23 @@ let JSWINDOWACTORS = { |
| 126 | 126 | remoteTypes: ["privilegedabout"],
|
| 127 | 127 | },
|
| 128 | 128 | |
| 129 | + AboutManual: {
|
|
| 130 | + parent: {
|
|
| 131 | + esModuleURI:
|
|
| 132 | + "moz-src:///browser/components/aboutmanual/AboutManualParent.sys.mjs",
|
|
| 133 | + },
|
|
| 134 | + child: {
|
|
| 135 | + esModuleURI:
|
|
| 136 | + "moz-src:///browser/components/aboutmanual/AboutManualChild.sys.mjs",
|
|
| 137 | + |
|
| 138 | + events: {
|
|
| 139 | + ManualLocaleSelected: { wantUntrusted: true },
|
|
| 140 | + },
|
|
| 141 | + },
|
|
| 142 | + |
|
| 143 | + matches: ["about:manual"],
|
|
| 144 | + },
|
|
| 145 | + |
|
| 129 | 146 | AboutMessagePreview: {
|
| 130 | 147 | parent: {
|
| 131 | 148 | esModuleURI: "resource:///actors/AboutMessagePreviewParent.sys.mjs",
|
| ... | ... | @@ -212,52 +212,45 @@ static nsAutoCString GetAboutModuleName(nsIURI* aURI) { |
| 212 | 212 | return path;
|
| 213 | 213 | }
|
| 214 | 214 | |
| 215 | -static nsTHashSet<nsCStringHashKey> GetManualLocales() {
|
|
| 216 | - nsTHashSet<nsCStringHashKey> locales;
|
|
| 217 | - RefPtr<nsZipArchive> zip = Omnijar::GetReader(Omnijar::APP);
|
|
| 218 | - if (!zip) {
|
|
| 219 | - // Probably a local build started with ./mach run
|
|
| 220 | - return locales;
|
|
| 221 | - }
|
|
| 222 | - UniquePtr<nsZipFind> find;
|
|
| 223 | - const nsAutoCString prefix("chrome/browser/content/browser/manual/");
|
|
| 224 | - nsAutoCString needle = prefix;
|
|
| 225 | - needle.Append("*.html");
|
|
| 226 | - if (NS_SUCCEEDED(zip->FindInit(needle.get(), getter_Transfers(find)))) {
|
|
| 227 | - const char* entryName;
|
|
| 228 | - uint16_t entryNameLen;
|
|
| 229 | - while (NS_SUCCEEDED(find->FindNext(&entryName, &entryNameLen))) {
|
|
| 230 | - // 5 is to remove the final `.html`
|
|
| 231 | - const size_t length = entryNameLen - prefix.Length() - 5;
|
|
| 232 | - locales.Insert(nsAutoCString(entryName + prefix.Length(), length));
|
|
| 233 | - }
|
|
| 234 | - }
|
|
| 235 | - return locales;
|
|
| 236 | -}
|
|
| 237 | - |
|
| 238 | 215 | static nsAutoCString GetManualChromeURI() {
|
| 239 | - static nsTHashSet<nsCStringHashKey> locales = GetManualLocales();
|
|
| 240 | - |
|
| 241 | - nsAutoCString reqLocale;
|
|
| 242 | - intl::LocaleService::GetInstance()->GetAppLocaleAsBCP47(reqLocale);
|
|
| 243 | - // Check every time the URL is needed in case the locale has changed.
|
|
| 244 | - // It might help also if we start allowing to change language, e.g., with a
|
|
| 245 | - // get parameter (see tor-browser#42675).
|
|
| 246 | - if (!locales.Contains(reqLocale) && reqLocale.Length() > 2 &&
|
|
| 247 | - reqLocale[2] == '-') {
|
|
| 248 | - // At the moment, codes in our manual output are either 2 letters (en) or
|
|
| 249 | - // 5 letters (pt-BR)
|
|
| 250 | - reqLocale.SetLength(2);
|
|
| 216 | + nsTArray<nsCString> availableLocales;
|
|
| 217 | + nsCString availableLocalesStr;
|
|
| 218 | + if (NS_SUCCEEDED(mozilla::Preferences::GetCString(
|
|
| 219 | + "torbrowser.manual.available-locales", availableLocalesStr)) &&
|
|
| 220 | + availableLocalesStr.Length() > 0) {
|
|
| 221 | + for (const nsACString& locale : availableLocalesStr.Split(',')) {
|
|
| 222 | + availableLocales.AppendElement(locale);
|
|
| 223 | + }
|
|
| 251 | 224 | }
|
| 252 | - if (!locales.Contains(reqLocale)) {
|
|
| 253 | - reqLocale = "en";
|
|
| 225 | + nsCString tryLocale;
|
|
| 226 | + if (!NS_SUCCEEDED(mozilla::Preferences::GetCString("torbrowser.manual.locale",
|
|
| 227 | + tryLocale)) ||
|
|
| 228 | + !availableLocales.Contains(tryLocale)) {
|
|
| 229 | + nsTArray<nsCString> appLocales;
|
|
| 230 | + intl::LocaleService::GetInstance()->GetAppLocalesAsBCP47(appLocales);
|
|
| 231 | + bool found = false;
|
|
| 232 | + for (size_t i = 0; i < appLocales.Length(); i++) {
|
|
| 233 | + tryLocale = appLocales[i];
|
|
| 234 | + if (availableLocales.Contains(tryLocale)) {
|
|
| 235 | + found = true;
|
|
| 236 | + break;
|
|
| 237 | + } else if (tryLocale.Length() > 3 && tryLocale[2] == '-') {
|
|
| 238 | + // Strip the region code and see if the lang matches.
|
|
| 239 | + tryLocale.SetLength(2);
|
|
| 240 | + if (availableLocales.Contains(tryLocale)) {
|
|
| 241 | + found = true;
|
|
| 242 | + break;
|
|
| 243 | + }
|
|
| 244 | + }
|
|
| 245 | + }
|
|
| 246 | + if (!found) {
|
|
| 247 | + tryLocale.AssignLiteral("en");
|
|
| 248 | + }
|
|
| 254 | 249 | }
|
| 255 | - |
|
| 256 | - // %s is the language
|
|
| 257 | - constexpr char model[] = "chrome://browser/content/manual/%s.html";
|
|
| 258 | - nsAutoCString url;
|
|
| 259 | - url.AppendPrintf(model, reqLocale.get());
|
|
| 260 | - return url;
|
|
| 250 | + nsAutoCString uri;
|
|
| 251 | + uri.AppendPrintf("chrome://browser/content/aboutmanual/aboutManual-%s.html",
|
|
| 252 | + tryLocale.get());
|
|
| 253 | + return uri;
|
|
| 261 | 254 | }
|
| 262 | 255 | |
| 263 | 256 | NS_IMETHODIMP
|
| 1 | +/**
|
|
| 2 | + * Actor child class for the about:manual page.
|
|
| 3 | + */
|
|
| 4 | +export class AboutManualChild extends JSWindowActorChild {
|
|
| 5 | + handleEvent(event) {
|
|
| 6 | + switch (event.type) {
|
|
| 7 | + case "ManualLocaleSelected": {
|
|
| 8 | + const locale = event.detail;
|
|
| 9 | + if (typeof locale === "string") {
|
|
| 10 | + this.sendAsyncMessage("AboutManual:LocaleSelected", locale);
|
|
| 11 | + }
|
|
| 12 | + }
|
|
| 13 | + }
|
|
| 14 | + }
|
|
| 15 | +} |
| 1 | +/**
|
|
| 2 | + * Actor parent class for the about:manual page.
|
|
| 3 | + */
|
|
| 4 | +export class AboutManualParent extends JSWindowActorParent {
|
|
| 5 | + receiveMessage(message) {
|
|
| 6 | + switch (message.name) {
|
|
| 7 | + case "AboutManual:LocaleSelected": {
|
|
| 8 | + const locale = message.data;
|
|
| 9 | + if (
|
|
| 10 | + Services.prefs
|
|
| 11 | + .getStringPref("torbrowser.manual.available-locales", "")
|
|
| 12 | + .split(",")
|
|
| 13 | + .includes(locale)
|
|
| 14 | + ) {
|
|
| 15 | + Services.prefs.setStringPref("torbrowser.manual.locale", locale);
|
|
| 16 | + this.browsingContext.reload(Ci.nsIWebNavigation.LOAD_FLAGS_NONE);
|
|
| 17 | + }
|
|
| 18 | + }
|
|
| 19 | + }
|
|
| 20 | + }
|
|
| 21 | +} |
| 1 | +"use strict";
|
|
| 2 | + |
|
| 3 | +function changePage(initialLoad) {
|
|
| 4 | + let page;
|
|
| 5 | + const hash = location.hash;
|
|
| 6 | + const id = hash.startsWith("#") ? hash.substr(1) : null;
|
|
| 7 | + let targetEl = null;
|
|
| 8 | + if (id) {
|
|
| 9 | + targetEl = document.getElementById(id);
|
|
| 10 | + page = targetEl?.closest(".olm-page");
|
|
| 11 | + }
|
|
| 12 | + if (!page) {
|
|
| 13 | + if (!initialLoad) {
|
|
| 14 | + // Make no change.
|
|
| 15 | + return;
|
|
| 16 | + }
|
|
| 17 | + page = document.getElementById("index");
|
|
| 18 | + }
|
|
| 19 | + const currPage = document.querySelector(".olm-page:not(.d-none)");
|
|
| 20 | + if (currPage === page) {
|
|
| 21 | + // No change in page.
|
|
| 22 | + return;
|
|
| 23 | + }
|
|
| 24 | + |
|
| 25 | + currPage?.classList.add("d-none");
|
|
| 26 | + page.classList.remove("d-none");
|
|
| 27 | + |
|
| 28 | + // If we are targeting an element that is not a page element, we want to
|
|
| 29 | + // scroll it into view (the focus position should have already shifted to
|
|
| 30 | + // point to it).
|
|
| 31 | + // Otherwise, if we have no target or the target is a page, we want to scroll
|
|
| 32 | + // to the top of the document so that the header is visible.
|
|
| 33 | + const doScroll = () => {
|
|
| 34 | + const scrollEl = targetEl && targetEl !== page ? targetEl : document.body;
|
|
| 35 | + scrollEl.scrollIntoView({
|
|
| 36 | + behavior: "instant",
|
|
| 37 | + block: "start",
|
|
| 38 | + inline: "start",
|
|
| 39 | + });
|
|
| 40 | + };
|
|
| 41 | + if (initialLoad) {
|
|
| 42 | + window.addEventListener("load", doScroll, { once: true });
|
|
| 43 | + } else {
|
|
| 44 | + doScroll();
|
|
| 45 | + }
|
|
| 46 | +}
|
|
| 47 | + |
|
| 48 | +window.addEventListener("DOMContentLoaded", () => {
|
|
| 49 | + const langDropdown = document.getElementById("language-menu-dropdown");
|
|
| 50 | + for (const langButton of langDropdown.querySelectorAll("button")) {
|
|
| 51 | + langButton.addEventListener("click", () => {
|
|
| 52 | + dispatchEvent(
|
|
| 53 | + new CustomEvent("ManualLocaleSelected", {
|
|
| 54 | + // The button's lang attribute is expected to match the locale's code.
|
|
| 55 | + detail: langButton.getAttribute("lang"),
|
|
| 56 | + bubbles: true,
|
|
| 57 | + })
|
|
| 58 | + );
|
|
| 59 | + });
|
|
| 60 | + }
|
|
| 61 | + |
|
| 62 | + changePage(true);
|
|
| 63 | +});
|
|
| 64 | + |
|
| 65 | +window.addEventListener("hashchange", () => {
|
|
| 66 | + changePage(false);
|
|
| 67 | +}); |
| 1 | +browser.jar:
|
|
| 2 | + content/browser/aboutmanual/aboutManual.js (content/aboutManual.js) |
| 1 | +JAR_MANIFESTS += ["jar.mn"]
|
|
| 2 | + |
|
| 3 | +MOZ_SRC_FILES += [
|
|
| 4 | + "AboutManualChild.sys.mjs",
|
|
| 5 | + "AboutManualParent.sys.mjs",
|
|
| 6 | +] |
| ... | ... | @@ -26,6 +26,7 @@ with Files("controlcenter/**"): |
| 26 | 26 | |
| 27 | 27 | DIRS += [
|
| 28 | 28 | "about",
|
| 29 | + "aboutmanual",
|
|
| 29 | 30 | "aboutlogins",
|
| 30 | 31 | "abouttor",
|
| 31 | 32 | "aboutwelcome",
|
| ... | ... | @@ -6,7 +6,7 @@ |
| 6 | 6 | <label
|
| 7 | 7 | class="text-link popup-notification-learnmore-link"
|
| 8 | 8 | is="text-link"
|
| 9 | - href="about:manual#onion-services_onion-service-authentication"
|
|
| 9 | + href="about:manual#features__onion-services___onion-service-auth"
|
|
| 10 | 10 | useoriginprincipal="true"
|
| 11 | 11 | data-l10n-id="onion-site-authentication-prompt-learn-more"
|
| 12 | 12 | />
|
| ... | ... | @@ -792,7 +792,7 @@ SettingGroupManager.registerGroups({ |
| 792 | 792 | onionSiteAuthentication: {
|
| 793 | 793 | l10nId: "onion-site-authentication-group",
|
| 794 | 794 | headingLevel: 2,
|
| 795 | - supportPage: "tor-manual:onion-services_onion-service-authentication",
|
|
| 795 | + supportPage: "tor-manual:features__onion-services___onion-service-auth",
|
|
| 796 | 796 | items: [
|
| 797 | 797 | {
|
| 798 | 798 | id: "onionSiteSavedKeys",
|
| ... | ... | @@ -10,7 +10,7 @@ |
| 10 | 10 | <html:span data-l10n-id="letterboxing-overview"></html:span>
|
| 11 | 11 | <html:a
|
| 12 | 12 | is="moz-support-link"
|
| 13 | - support-page="tor-manual:anti-fingerprinting_letterboxing"
|
|
| 13 | + support-page="tor-manual:features__fingerprinting-protections___letterboxing"
|
|
| 14 | 14 | data-l10n-id="letterboxing-learn-more"
|
| 15 | 15 | ></html:a>
|
| 16 | 16 | </description>
|
| ... | ... | @@ -18,7 +18,7 @@ |
| 18 | 18 | <html:a
|
| 19 | 19 | is="moz-support-link"
|
| 20 | 20 | id="securityLevel-learnMore"
|
| 21 | - support-page="tor-manual:security-settings"
|
|
| 21 | + support-page="tor-manual:features__security-levels"
|
|
| 22 | 22 | data-l10n-id="security-level-panel-learn-more-link"
|
| 23 | 23 | ></html:a>
|
| 24 | 24 | <html:img id="securityLevel-background-image" alt="" />
|
| ... | ... | @@ -13,7 +13,7 @@ |
| 13 | 13 | ></html:span>
|
| 14 | 14 | <html:a
|
| 15 | 15 | is="moz-support-link"
|
| 16 | - support-page="tor-manual:security-settings"
|
|
| 16 | + support-page="tor-manual:features__security-levels"
|
|
| 17 | 17 | data-l10n-id="security-level-preferences-learn-more-link"
|
| 18 | 18 | ></html:a>
|
| 19 | 19 | </description>
|
| ... | ... | @@ -13,7 +13,7 @@ SettingGroupManager.registerGroups({ |
| 13 | 13 | connectionStatus: {
|
| 14 | 14 | inProgress: true,
|
| 15 | 15 | l10nId: "tor-connection-internet-status-group",
|
| 16 | - supportPage: "tor-manual:about",
|
|
| 16 | + supportPage: "tor-manual:getting-started__about-tor-browser",
|
|
| 17 | 17 | headingLevel: 2,
|
| 18 | 18 | items: [
|
| 19 | 19 | {
|
| ... | ... | @@ -18,7 +18,7 @@ |
| 18 | 18 | <label
|
| 19 | 19 | class="learnMore text-link"
|
| 20 | 20 | is="text-link"
|
| 21 | - href="about:manual#about"
|
|
| 21 | + href="about:manual#getting-started__about-tor-browser"
|
|
| 22 | 22 | useoriginprincipal="true"
|
| 23 | 23 | data-l10n-id="tor-connection-browser-learn-more-link"
|
| 24 | 24 | />
|
| ... | ... | @@ -129,7 +129,7 @@ |
| 129 | 129 | <label
|
| 130 | 130 | class="learnMore text-link"
|
| 131 | 131 | is="text-link"
|
| 132 | - href="about:manual#bridges"
|
|
| 132 | + href="about:manual#circumvention__unblocking-tor"
|
|
| 133 | 133 | useoriginprincipal="true"
|
| 134 | 134 | data-l10n-id="tor-bridges-learn-more-link"
|
| 135 | 135 | />
|
| ... | ... | @@ -37,7 +37,7 @@ |
| 37 | 37 | <label
|
| 38 | 38 | is="text-link"
|
| 39 | 39 | class="learnMore text-link"
|
| 40 | - href="about:manual#bridges"
|
|
| 40 | + href="about:manual#circumvention__unblocking-tor"
|
|
| 41 | 41 | useoriginprincipal="true"
|
| 42 | 42 | data-l10n-id="user-provide-bridge-dialog-learn-more"
|
| 43 | 43 | />
|
| ... | ... | @@ -372,7 +372,7 @@ function initOnionError() { |
| 372 | 372 | const learnMore = document.getElementById("learnMoreContainer");
|
| 373 | 373 | learnMore.hidden = false;
|
| 374 | 374 | const learnMoreLink = document.getElementById("learnMoreLink");
|
| 375 | - learnMoreLink.href = "about:manual#onion-services";
|
|
| 375 | + learnMoreLink.href = "about:manual#features__onion-services";
|
|
| 376 | 376 | |
| 377 | 377 | setFocus("#netErrorButtonContainer > .try-again");
|
| 378 | 378 |
| ... | ... | @@ -243,7 +243,7 @@ const Loader = { |
| 243 | 243 | );
|
| 244 | 244 | return {
|
| 245 | 245 | ...tsb.getStrings(strings),
|
| 246 | - learnMoreURL: "about:manual#onion-services",
|
|
| 246 | + learnMoreURL: "about:manual#features__onion-services",
|
|
| 247 | 247 | // XUL popups cannot open about: URLs, but we are online when showing the notification, so just use the online version
|
| 248 | 248 | learnMoreURLNotification: `https://tb-manual.torproject.org/${getLocale()}/onion-services/`,
|
| 249 | 249 | };
|