Commit 4375bf23 authored by Pier Angelo Vendrame's avatar Pier Angelo Vendrame 🎃
Browse files

TB 11698: Incorporate Tor Browser Manual pages into Tor Browser

This patch associates the about:manual page to a translated page that
must be injected to browser/omni.ja after the build.
The content must be placed in chrome/browser/content/browser/manual/, so
that is then available at chrome://browser/content/manual/.
We preferred giving absolute freedom to the web team, rather than having
to change the patch in case of changes on the documentation.
parent 6b9de8b8
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -458,6 +458,10 @@
              <menupopup id="menu_HelpPopup">
<!-- Note: Items under here are cloned to the AppMenu Help submenu. The cloned items
     have their strings defined by appmenu-data-l10n-id. -->
                <!-- Add Tor Browser manual link -->
                <menuitem id="torBrowserUserManual"
                          data-l10n-id="menu-open-tor-manual"
                          appmenu-data-l10n-id="appmenu-open-tor-manual"/>
                <menuitem id="menu_openHelp"
                          hidden="true"
                          data-l10n-id="menu-get-help"
+7 −0
Original line number Diff line number Diff line
@@ -116,6 +116,13 @@ document.addEventListener(
            });
          }
          break;

        case "torBrowserUserManual":
          gBrowser.selectedTab = gBrowser.addTab("about:manual", {
            triggeringPrincipal:
              Services.scriptSecurityManager.getSystemPrincipal(),
          });
          break;
      }
    });

+67 −0
Original line number Diff line number Diff line
@@ -16,6 +16,11 @@
#include "mozilla/dom/ContentChild.h"
#include "mozilla/browser/NimbusFeatures.h"

// For Tor Browser manual
#include "nsTHashSet.h"
#include "mozilla/intl/LocaleService.h"
#include "mozilla/Omnijar.h"

#define PROFILES_ENABLED_PREF "browser.profiles.enabled"
#define ABOUT_WELCOME_CHROME_URL \
  "chrome://browser/content/aboutwelcome/aboutwelcome.html"
@@ -185,6 +190,12 @@ static const RedirEntry kRedirMap[] = {
         nsIAboutModule::URI_CAN_LOAD_IN_CHILD | nsIAboutModule::ALLOW_SCRIPT |
         nsIAboutModule::HIDE_FROM_ABOUTABOUT |
         nsIAboutModule::IS_SECURE_CHROME_UI},
    // The correct URI must be obtained by GetManualChromeURI
    {"manual", "about:blank",
     nsIAboutModule::URI_SAFE_FOR_UNTRUSTED_CONTENT |
         nsIAboutModule::ALLOW_SCRIPT | nsIAboutModule::URI_MUST_LOAD_IN_CHILD |
         nsIAboutModule::URI_CAN_LOAD_IN_PRIVILEGEDABOUT_PROCESS |
         nsIAboutModule::IS_SECURE_CHROME_UI},
};

static nsAutoCString GetAboutModuleName(nsIURI* aURI) {
@@ -201,6 +212,54 @@ static nsAutoCString GetAboutModuleName(nsIURI* aURI) {
  return path;
}

static nsTHashSet<nsCStringHashKey> GetManualLocales() {
  nsTHashSet<nsCStringHashKey> locales;
  RefPtr<nsZipArchive> zip = Omnijar::GetReader(Omnijar::APP);
  if (!zip) {
    // Probably a local build started with ./mach run
    return locales;
  }
  UniquePtr<nsZipFind> find;
  const nsAutoCString prefix("chrome/browser/content/browser/manual/");
  nsAutoCString needle = prefix;
  needle.Append("*.html");
  if (NS_SUCCEEDED(zip->FindInit(needle.get(), getter_Transfers(find)))) {
    const char* entryName;
    uint16_t entryNameLen;
    while (NS_SUCCEEDED(find->FindNext(&entryName, &entryNameLen))) {
      // 5 is to remove the final `.html`
      const size_t length = entryNameLen - prefix.Length() - 5;
      locales.Insert(nsAutoCString(entryName + prefix.Length(), length));
    }
  }
  return locales;
}

static nsAutoCString GetManualChromeURI() {
  static nsTHashSet<nsCStringHashKey> locales = GetManualLocales();

  nsAutoCString reqLocale;
  intl::LocaleService::GetInstance()->GetAppLocaleAsBCP47(reqLocale);
  // Check every time the URL is needed in case the locale has changed.
  // It might help also if we start allowing to change language, e.g., with a
  // get parameter (see tor-browser#42675).
  if (!locales.Contains(reqLocale) && reqLocale.Length() > 2 &&
      reqLocale[2] == '-') {
    // At the moment, codes in our manual output are either 2 letters (en) or
    // 5 letters (pt-BR)
    reqLocale.SetLength(2);
  }
  if (!locales.Contains(reqLocale)) {
    reqLocale = "en";
  }

  // %s is the language
  constexpr char model[] = "chrome://browser/content/manual/%s.html";
  nsAutoCString url;
  url.AppendPrintf(model, reqLocale.get());
  return url;
}

NS_IMETHODIMP
AboutRedirector::NewChannel(nsIURI* aURI, nsILoadInfo* aLoadInfo,
                            nsIChannel** result) {
@@ -238,6 +297,10 @@ AboutRedirector::NewChannel(nsIURI* aURI, nsILoadInfo* aLoadInfo,
        url.AssignASCII(BASE_BROWSER_HOME_PAGE_URL);
      }

      if (path.EqualsLiteral("manual")) {
        url = GetManualChromeURI();
      }

      // fall back to the specified url in the map
      if (url.IsEmpty()) {
        url.AssignASCII(redir.url);
@@ -296,6 +359,10 @@ AboutRedirector::GetChromeURI(nsIURI* aURI, nsIURI** chromeURI) {

  nsAutoCString name = GetAboutModuleName(aURI);

  if (name.EqualsLiteral("manual")) {
    return NS_NewURI(chromeURI, GetManualChromeURI());
  }

  for (const auto& redir : kRedirMap) {
    if (name.Equals(redir.id)) {
      return NS_NewURI(chromeURI, redir.url);
+1 −0
Original line number Diff line number Diff line
@@ -13,6 +13,7 @@ pages = [
    'keyboard',
    'logins',
    'loginsimportreport',
    'manual',
    'messagepreview',
    'newtab',
    'opentabs',
+6 −0
Original line number Diff line number Diff line
@@ -823,6 +823,12 @@ const PanelUI = {
      case "appMenu_helpPolicySupport":
        openTrustedLinkIn(Services.policies.getSupportMenu().URL.href, "tab");
        break;
      case "appMenu_torBrowserUserManual":
        gBrowser.selectedTab = gBrowser.addTab("about:manual", {
          triggeringPrincipal:
            Services.scriptSecurityManager.getSystemPrincipal(),
        });
        break;
    }
  },