lists.torproject.org
Sign In Sign Up
Manage this list Sign In Sign Up

Keyboard Shortcuts

Thread View

  • j: Next unread message
  • k: Previous unread message
  • j a: Jump to all threads
  • j l: Jump to MailingList overview

tbb-commits

Thread Start a new thread
Threads by month
  • ----- 2026 -----
  • November
  • October
  • September
  • August
  • July
  • June
  • May
  • April
  • 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
tbb-commits@lists.torproject.org

  • 1 participants
  • 21316 discussions
[Git][tpo/applications/tor-browser][tor-browser-128.4.0esr-14.5-1] fixup! Adding issue and merge request templates
by morgan (@morgan) 30 Oct '24

30 Oct '24
morgan pushed to branch tor-browser-128.4.0esr-14.5-1 at The Tor Project / Applications / Tor Browser Commits: 35ef7d82 by Henry Wilkes at 2024-10-29T21:24:47+00:00 fixup! Adding issue and merge request templates Bug 43262: Update QA desktop checklist to include testing saved keys and their preferences. - - - - - 1 changed file: - .gitlab/issue_templates/QA - Desktop.md Changes: ===================================== .gitlab/issue_templates/QA - Desktop.md ===================================== @@ -135,6 +135,10 @@ Manual QA test check-list for major desktop releases. Please copy/paste form int - [ ] Onion-Location pill - [ ] Client authentication - You can create an ephemeral client-auth onion-service using [onion share](https://onionshare.org) + - [ ] Remember key option saves the key between sessions. + - [ ] Saved keys are viewable in preferences (privacy). + - [ ] Can remove individual keys. + - [ ] Can remove all keys at once. - [ ] Onion service errors - [ ] invalid onion: http://invalid.onion - [ ] onion offline: http://wfdn32ds656ycma5gvrh7duvdvxbg2ygzr3no3ijsya25qm6nnko4iqd.onion/ View it on GitLab: https://gitlab.torproject.org/tpo/applications/tor-browser/-/commit/35ef7d8… -- View it on GitLab: https://gitlab.torproject.org/tpo/applications/tor-browser/-/commit/35ef7d8… You're receiving this email because of your account on gitlab.torproject.org.
1 0
0 0
[Git][tpo/applications/tor-browser-build][main] Update release prep issue templates (Tor Browser Legacy)
by morgan (@morgan) 30 Oct '24

30 Oct '24
morgan pushed to branch main at The Tor Project / Applications / tor-browser-build Commits: 344327b6 by Nicolas Vigier at 2024-10-29T21:19:49+00:00 Update release prep issue templates (Tor Browser Legacy) Add missing step when manually deploying update responses for legacy-only release. - - - - - 1 changed file: - .gitlab/issue_templates/Release Prep - Tor Browser Legacy.md Changes: ===================================== .gitlab/issue_templates/Release Prep - Tor Browser Legacy.md ===================================== @@ -251,6 +251,22 @@ popd ```bash make torbrowser-update_responses-release ``` + - [ ] Commit new update responses to tor-browser-update-responses.git: + - [ ] Run: + ```bash + updaterespdir=/path/to/tor-browser-update-responses.git + cp torbrowser/release/update-responses/update-responses-release-${TOR_BROWSER_VERSION}.tar "$updaterespdir" + cd "$updaterespdir" + git pull + rm -Rf update_3/release + tar -C update_3 update-responses-release-${TOR_BROWSER_VERSION}.tar + rm update-responses-release-${TOR_BROWSER_VERSION}.tar + git add update_3/release + git commit -m "release: new version, ${TOR_BROWSER_VERSION}" + git push + # print the commit hash and copy past it for the next step + git show -s --format=%H + ``` - On `staticiforme.torproject.org`, deploy new update responses: - **NOTE**: for now this is a bit janky, we should somehow update the workflow to be a bit less hacky - [ ] Edit an existing `deploy_update_responses-release.sh` script in your `HOME` directory with the newly pushed commit hash View it on GitLab: https://gitlab.torproject.org/tpo/applications/tor-browser-build/-/commit/3… -- View it on GitLab: https://gitlab.torproject.org/tpo/applications/tor-browser-build/-/commit/3… You're receiving this email because of your account on gitlab.torproject.org.
1 0
0 0
[Git][tpo/applications/tor-browser][tor-browser-128.4.0esr-14.5-1] fixup! [android] Modify UI/UX
by morgan (@morgan) 30 Oct '24

30 Oct '24
morgan pushed to branch tor-browser-128.4.0esr-14.5-1 at The Tor Project / Applications / Tor Browser Commits: 474dd858 by cypherpunks1 at 2024-10-29T21:13:24+00:00 fixup! [android] Modify UI/UX Bug 43241: Improve hiding non-private tab features on Android - - - - - 3 changed files: - mobile/android/fenix/app/src/main/java/org/mozilla/fenix/components/toolbar/DefaultToolbarMenu.kt - mobile/android/fenix/app/src/main/java/org/mozilla/fenix/home/HomeMenu.kt - mobile/android/fenix/app/src/main/java/org/mozilla/fenix/settings/SettingsFragment.kt Changes: ===================================== mobile/android/fenix/app/src/main/java/org/mozilla/fenix/components/toolbar/DefaultToolbarMenu.kt ===================================== @@ -218,13 +218,13 @@ open class DefaultToolbarMenu( onItemTapped.invoke(ToolbarMenu.Item.NewTorCircuit) } - //private val historyItem = BrowserMenuImageText( - // context.getString(R.string.library_history), - // R.drawable.ic_history, - // primaryTextColor() - //) { - // onItemTapped.invoke(ToolbarMenu.Item.History) - //} + private val historyItem = BrowserMenuImageText( + context.getString(R.string.library_history), + R.drawable.ic_history, + primaryTextColor(), + ) { + onItemTapped.invoke(ToolbarMenu.Item.History) + } private val downloadsItem = BrowserMenuImageText( context.getString(R.string.library_downloads), @@ -419,7 +419,7 @@ open class DefaultToolbarMenu( newCircuitItem, BrowserMenuDivider(), bookmarksItem, - //historyItem, + if (context.settings().shouldDisableNormalMode) null else historyItem, downloadsItem, passwordsItem, extensionsItem, ===================================== mobile/android/fenix/app/src/main/java/org/mozilla/fenix/home/HomeMenu.kt ===================================== @@ -131,13 +131,13 @@ class HomeMenu( onItemTapped.invoke(Item.Bookmarks) } - // val historyItem = BrowserMenuImageText( - // context.getString(R.string.library_history), - // R.drawable.ic_history, - // primaryTextColor, - // ) { - // onItemTapped.invoke(Item.History) - // } + val historyItem = BrowserMenuImageText( + context.getString(R.string.library_history), + R.drawable.ic_history, + primaryTextColor, + ) { + onItemTapped.invoke(Item.History) + } val downloadsItem = BrowserMenuImageText( context.getString(R.string.library_downloads), @@ -228,7 +228,7 @@ class HomeMenu( val menuItems = listOfNotNull( bookmarksItem, - //historyItem, + if (context.settings().shouldDisableNormalMode) null else historyItem, downloadsItem, passwordsItem, // extensionsItem, ===================================== mobile/android/fenix/app/src/main/java/org/mozilla/fenix/settings/SettingsFragment.kt ===================================== @@ -251,9 +251,11 @@ class SettingsFragment : PreferenceFragmentCompat() { getString(R.string.delete_browsing_data_quit_off) } - val tabSettingsPreference = - requirePreference<Preference>(R.string.pref_key_tabs) - tabSettingsPreference.summary = context?.settings()?.getTabTimeoutString() + if (!settings.shouldDisableNormalMode) { + val tabSettingsPreference = + requirePreference<Preference>(R.string.pref_key_tabs) + tabSettingsPreference.summary = context?.settings()?.getTabTimeoutString() + } // val autofillPreference = requirePreference<Preference>(R.string.pref_key_credit_cards) // autofillPreference.title = if (settings.addressFeature) { View it on GitLab: https://gitlab.torproject.org/tpo/applications/tor-browser/-/commit/474dd85… -- View it on GitLab: https://gitlab.torproject.org/tpo/applications/tor-browser/-/commit/474dd85… You're receiving this email because of your account on gitlab.torproject.org.
1 0
0 0
[Git][tpo/applications/tor-browser][tor-browser-128.4.0esr-14.5-1] 3 commits: fixup! Bug 16940: After update, load local change notes.
by morgan (@morgan) 30 Oct '24

30 Oct '24
morgan pushed to branch tor-browser-128.4.0esr-14.5-1 at The Tor Project / Applications / Tor Browser Commits: 6d2b4add by Henry Wilkes at 2024-10-29T21:02:40+00:00 fixup! Bug 16940: After update, load local change notes. Bug 42186: Revert the entire commit. - - - - - 201d50e6 by Henry Wilkes at 2024-10-29T21:02:40+00:00 fixup! Add TorStrings module for localization Bug 42186: Drop about:tbupdate. - - - - - b4b207fa by Henry Wilkes at 2024-10-29T21:02:40+00:00 fixup! Bug 7494: Create local home page for TBB. Bug 42186: Move override page logic to about:tor commit. - - - - - 15 changed files: - − browser/actors/AboutTBUpdateChild.sys.mjs - − browser/actors/AboutTBUpdateParent.sys.mjs - browser/actors/moz.build - − browser/base/content/abouttbupdate/aboutTBUpdate.css - − browser/base/content/abouttbupdate/aboutTBUpdate.js - − browser/base/content/abouttbupdate/aboutTBUpdate.xhtml - browser/base/content/browser.js - browser/base/jar.mn - browser/components/BrowserContentHandler.sys.mjs - browser/components/BrowserGlue.sys.mjs - browser/components/about/AboutRedirector.cpp - browser/components/about/components.conf - toolkit/modules/RemotePageAccessManager.sys.mjs - − toolkit/torbutton/chrome/locale/en-US/aboutTBUpdate.dtd - toolkit/torbutton/jar.mn Changes: ===================================== browser/actors/AboutTBUpdateChild.sys.mjs deleted ===================================== @@ -1,8 +0,0 @@ -// Copyright (c) 2020, The Tor Project, Inc. -// See LICENSE for licensing information. -// -// vim: set sw=2 sts=2 ts=8 et syntax=javascript: - -import { RemotePageChild } from "resource://gre/actors/RemotePageChild.sys.mjs"; - -export class AboutTBUpdateChild extends RemotePageChild {} ===================================== browser/actors/AboutTBUpdateParent.sys.mjs deleted ===================================== @@ -1,128 +0,0 @@ -// Copyright (c) 2020, The Tor Project, Inc. -// See LICENSE for licensing information. -// -// vim: set sw=2 sts=2 ts=8 et syntax=javascript: - -import { AppConstants } from "resource://gre/modules/AppConstants.sys.mjs"; - -const kRequestUpdateMessageName = "FetchUpdateData"; - -/** - * This code provides services to the about:tbupdate page. Whenever - * about:tbupdate needs to do something chrome-privileged, it sends a - * message that's handled here. It is modeled after Mozilla's about:home - * implementation. - */ -export class AboutTBUpdateParent extends JSWindowActorParent { - async receiveMessage(aMessage) { - if (aMessage.name == kRequestUpdateMessageName) { - return this.getReleaseNoteInfo(); - } - return undefined; - } - - get moreInfoURL() { - try { - return Services.prefs.getCharPref("torbrowser.post_update.url"); - } catch (e) {} - - // Use the default URL as a fallback. - return Services.urlFormatter.formatURLPref("startup.homepage_override_url"); - } - - // Read the text from the beginning of the changelog file that is located - // at TorBrowser/Docs/ChangeLog.txt (or, - // TorBrowser.app/Contents/Resources/TorBrowser/Docs/ on macOS, to support - // Gatekeeper signing) and return an object that contains the following - // properties: - // version e.g., Tor Browser 8.5 - // releaseDate e.g., March 31 2019 - // releaseNotes details of changes (lines 2 - end of ChangeLog.txt) - // We attempt to parse the first line of ChangeLog.txt to extract the - // version and releaseDate. If parsing fails, we return the entire first - // line in version and omit releaseDate. - async getReleaseNoteInfo() { - let info = { moreInfoURL: this.moreInfoURL }; - - try { - // "XREExeF".parent is the directory that contains firefox, i.e., - // Browser/ or, TorBrowser.app/Contents/MacOS/ on macOS. - let f = Services.dirsvc.get("XREExeF", Ci.nsIFile).parent; - if (AppConstants.platform === "macosx") { - f = f.parent; - f.append("Resources"); - } - f.append("TorBrowser"); - f.append("Docs"); - f.append("ChangeLog.txt"); - - // NOTE: We load in the entire file, but only use the first few lines - // before the first blank line. - const logLines = (await IOUtils.readUTF8(f.path)) - .replace(/\n\r?\n.*/ms, "") - .split(/\n\r?/); - - // Read the first line to get the version and date. - // Assume everything after the last "-" is the date. - const firstLine = logLines.shift(); - const match = firstLine?.match(/(.*)-+(.*)/); - if (match) { - info.version = match[1].trim(); - info.releaseDate = match[2].trim(); - } else { - // No date. - info.version = firstLine?.trim(); - } - - // We want to read the rest of the release notes as a tree. Each entry - // will contain the text for that line. - // We choose a negative index for the top node of this tree to ensure no - // line will appear less indented. - const topEntry = { indent: -1, children: undefined }; - let prevEntry = topEntry; - - for (let line of logLines) { - const indent = line.match(/^ */)[0]; - line = line.trim(); - if (line.startsWith("*")) { - // Treat as a bullet point. - let entry = { - text: line.replace(/^\*\s/, ""), - indent: indent.length, - }; - let parentEntry; - if (entry.indent > prevEntry.indent) { - // A sub-list of the previous item. - prevEntry.children = []; - parentEntry = prevEntry; - } else { - // Same list or end of sub-list. - // Search for the first parent whose indent comes before ours. - parentEntry = prevEntry.parent; - while (entry.indent <= parentEntry.indent) { - parentEntry = parentEntry.parent; - } - } - entry.parent = parentEntry; - parentEntry.children.push(entry); - prevEntry = entry; - } else if (prevEntry === topEntry) { - // Unexpected, missing bullet point on first line. - // Place as its own bullet point instead, and set as prevEntry for the - // next loop. - prevEntry = { text: line, indent: indent.length, parent: topEntry }; - topEntry.children = [prevEntry]; - } else { - // Append to the previous bullet point. - prevEntry.text += ` ${line}`; - } - } - - info.releaseNotes = topEntry.children; - } catch (e) { - console.error(e); - } - - return info; - } -} ===================================== browser/actors/moz.build ===================================== @@ -90,9 +90,3 @@ FINAL_TARGET_FILES.actors += [ BROWSER_CHROME_MANIFESTS += [ "test/browser/browser.toml", ] - -if CONFIG["BASE_BROWSER_UPDATE"]: - FINAL_TARGET_FILES.actors += [ - "AboutTBUpdateChild.sys.mjs", - "AboutTBUpdateParent.sys.mjs", - ] ===================================== browser/base/content/abouttbupdate/aboutTBUpdate.css deleted ===================================== @@ -1,70 +0,0 @@ -/* - * Copyright (c) 2019, The Tor Project, Inc. - * See LICENSE for licensing information. - * - * vim: set sw=2 sts=2 ts=8 et syntax=css: - */ - -:root { - --abouttor-text-color: white; - --abouttor-bg-toron-color: #420C5D; -} - -body { - font-family: Helvetica, Arial, sans-serif; - color: var(--abouttor-text-color); - background-color: var(--abouttor-bg-toron-color); - margin-block: 40px; - margin-inline: 50px; - display: grid; - grid-template-columns: auto auto; - align-items: baseline; - gap: 40px 50px; -} - -body > *:not([hidden]) { - display: contents; -} - -.label-column { - grid-column: 1; -} - -.content { - grid-column: 2; -} - -.content.en-US-content { - font-family: monospace; - line-height: 1.4; -} - -.label-column, .content { - margin: 0; - padding: 0; - font-size: 1rem; - font-weight: normal; -} - -a { - color: inherit; -} - -.no-line-break { - white-space: nowrap; -} - -ul { - padding-inline: 1em 0; -} - -h3, h4 { - font-size: 1.1rem; - font-weight: bold; -} - -h3.build-system-heading { - font-size: 1.5rem; - font-weight: normal; - margin-block-start: 3em; -} ===================================== browser/base/content/abouttbupdate/aboutTBUpdate.js deleted ===================================== @@ -1,110 +0,0 @@ -// Copyright (c) 2020, The Tor Project, Inc. -// See LICENSE for licensing information. -// -// vim: set sw=2 sts=2 ts=8 et syntax=javascript: - -/* eslint-env mozilla/remote-page */ - -/** - * An object representing a bullet point in the release notes. - * - * typedef {Object} ReleaseBullet - * @property {string} text - The text for this bullet point. - * @property {?Array<ReleaseBullet>} children - A sub-list of bullet points. - */ - -/** - * Fill an element with the given list of release bullet points. - * - * @param {Element} container - The element to fill with bullet points. - * @param {Array<ReleaseBullet>} bulletPoints - The list of bullet points. - * @param {string} [childTag="h3"] - The element tag name to use for direct - * children. Initially, the children are h3 sub-headings. - */ -function fillReleaseNotes(container, bulletPoints, childTag = "h3") { - for (const { text, children } of bulletPoints) { - const childEl = document.createElement(childTag); - // Keep dashes like "[tor-browser]" on the same line by nowrapping the word. - for (const [index, part] of text.split(/(\S+-\S+)/).entries()) { - if (!part) { - continue; - } - const span = document.createElement("span"); - span.textContent = part; - span.classList.toggle("no-line-break", index % 2); - childEl.appendChild(span); - } - container.appendChild(childEl); - if (children) { - if (childTag == "h3" && text.toLowerCase() === "build system") { - // Special case: treat the "Build System" heading's children as - // sub-headings. - childEl.classList.add("build-system-heading"); - fillReleaseNotes(container, children, "h4"); - } else { - const listEl = document.createElement("ul"); - fillReleaseNotes(listEl, children, "li"); - if (childTag == "li") { - // Insert within the "li" element. - childEl.appendChild(listEl); - } else { - container.appendChild(listEl); - } - } - } - } -} - -/** - * Set the content for the specified container, or hide it if we have no - * content. - * - * @template C - * @param {string} containerId - The id for the container. - * @param {?C} content - The content for this container, or a falsey value if - * the container has no content. - * @param {function(contentEl: Elemenet, content: C)} [fillContent] - A function - * to fill the ".content" contentEl with the given 'content'. If unspecified, - * the 'content' will become the contentEl's textContent. - */ -function setContent(containerId, content, fillContent) { - const container = document.getElementById(containerId); - if (!content) { - container.hidden = true; - return; - } - const contentEl = container.querySelector(".content"); - // Release notes are only in English. - contentEl.setAttribute("lang", "en-US"); - contentEl.setAttribute("dir", "ltr"); - contentEl.classList.add("en-US-content"); - if (fillContent) { - fillContent(contentEl, content); - } else { - contentEl.textContent = content; - } -} - -/** - * Callback when we receive the update details. - * - * @param {Object} aData - The update details. - * @param {?string} aData.version - The update version. - * @param {?string} aData.releaseDate - The release date. - * @param {?string} aData.moreInfoURL - A URL for more info. - * @param {?Array<ReleaseBullet>} aData.releaseNotes - Release notes as bullet - * points. - */ -function onUpdate(aData) { - setContent("version-row", aData.version); - setContent("releasedate-row", aData.releaseDate); - setContent("releasenotes", aData.releaseNotes, fillReleaseNotes); - - if (aData.moreInfoURL) { - document.getElementById("infolink").setAttribute("href", aData.moreInfoURL); - } else { - document.getElementById("fullinfo").hidden = true; - } -} - -RPMSendQuery("FetchUpdateData").then(onUpdate); ===================================== browser/base/content/abouttbupdate/aboutTBUpdate.xhtml deleted ===================================== @@ -1,52 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> - -<!DOCTYPE html [ <!ENTITY % htmlDTD PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "DTD/xhtml1-strict.dtd"> -%htmlDTD; -<!ENTITY % tbUpdateDTD SYSTEM "chrome://browser/locale/aboutTBUpdate.dtd"> -%tbUpdateDTD; ]> - -<html xmlns="http://www.w3.org/1999/xhtml"> - <head> - <meta - http-equiv="Content-Security-Policy" - content="default-src chrome:; object-src 'none'" - /> - <title>&aboutTBUpdate.changelogTitle;</title> - <link - rel="stylesheet" - type="text/css" - href="chrome://browser/content/abouttbupdate/aboutTBUpdate.css" - /> - <script - src="chrome://browser/content/abouttbupdate/aboutTBUpdate.js" - type="text/javascript" - /> - <!-- Hack: we are not using Fluent translations in this page (yet), but we use - - this tag so it sets up the page automatically for us. --> - <link rel="localization" href="branding/brand.ftl" /> - </head> - <body> - <!-- NOTE: We don't use the <dl>, <dt> and <dd> elements to form name-value - - pairs because this semantics is relatively new, whilst firefox - - currently still maps these to the more limited "definitionlist", "term" - - and "definition" roles. --> - <div id="version-row"> - <span class="label-column">&aboutTBUpdate.version;</span> - <span class="content"></span> - </div> - <div id="releasedate-row"> - <span class="label-column">&aboutTBUpdate.releaseDate;</span> - <span class="content"></span> - </div> - <div id="fullinfo"> - <p class="content"> - &aboutTBUpdate.linkPrefix;<a id="infolink">&aboutTBUpdate.linkLabel;</a - >&aboutTBUpdate.linkSuffix; - </p> - </div> - <section id="releasenotes"> - <h2 class="label-column">&aboutTBUpdate.releaseNotes;</h2> - <div class="content"></div> - </section> - </body> -</html> ===================================== browser/base/content/browser.js ===================================== @@ -771,10 +771,6 @@ if (Services.prefs.getBoolPref("browser.profiles.enabled")) { gInitialPages.push("about:profilemanager"); } -if (AppConstants.BASE_BROWSER_UPDATE) { - gInitialPages.push("about:tbupdate"); -} - function isInitialPage(url) { if (!(url instanceof Ci.nsIURI)) { try { ===================================== browser/base/jar.mn ===================================== @@ -33,11 +33,6 @@ browser.jar: content/browser/aboutTabCrashed.css (content/aboutTabCrashed.css) content/browser/aboutTabCrashed.js (content/aboutTabCrashed.js) content/browser/aboutTabCrashed.xhtml (content/aboutTabCrashed.xhtml) -#ifdef BASE_BROWSER_UPDATE - content/browser/abouttbupdate/aboutTBUpdate.xhtml (content/abouttbupdate/aboutTBUpdate.xhtml) - content/browser/abouttbupdate/aboutTBUpdate.js (content/abouttbupdate/aboutTBUpdate.js) - content/browser/abouttbupdate/aboutTBUpdate.css (content/abouttbupdate/aboutTBUpdate.css) -#endif content/browser/blanktab.html (content/blanktab.html) content/browser/browser.css (content/browser.css) content/browser/browser.js (content/browser.js) ===================================== browser/components/BrowserContentHandler.sys.mjs ===================================== @@ -783,16 +783,6 @@ nsBrowserContentHandler.prototype = { // into account because that requires waiting for the session file // to be read. If a crash occurs after updating, before restarting, // we may open the startPage in addition to restoring the session. - // - // Tor Browser: Instead of opening the post-update "override page" - // directly, we ensure that about:tor will be opened in a special - // mode that notifies the user that their browser was updated. - // The about:tor page will provide a link to the override page - // where the user can learn more about the update, as well as a - // link to the Tor Browser changelog page (about:tbupdate). The - // override page URL comes from the openURL attribute within the - // updates.xml file or, if no showURL action is present, from the - // startup.homepage_override_url pref. willRestoreSession = lazy.SessionStartup.isAutomaticRestoreEnabled(); @@ -887,6 +877,13 @@ nsBrowserContentHandler.prototype = { old_forkVersion ); if (overridePage && AppConstants.BASE_BROWSER_UPDATE) { + // Tor Browser: Instead of opening the post-update "override page" + // directly, we ensure that about:tor will be opened, which should + // notify the user that their browser was updated. + // + // The overridePage comes from the openURL attribute within the + // updates.xml file or, if no showURL action is present, from the + // startup.homepage_override_url pref. Services.prefs.setCharPref( "torbrowser.post_update.url", overridePage ===================================== browser/components/BrowserGlue.sys.mjs ===================================== @@ -1022,21 +1022,6 @@ let JSWINDOWACTORS = { }, }; -if (AppConstants.BASE_BROWSER_UPDATE) { - JSWINDOWACTORS.AboutTBUpdate = { - parent: { - esModuleURI: "resource:///actors/AboutTBUpdateParent.sys.mjs", - }, - child: { - esModuleURI: "resource:///actors/AboutTBUpdateChild.sys.mjs", - events: { - DOMWindowCreated: { capture: true }, - }, - }, - matches: ["about:tbupdate"], - }; -} - ChromeUtils.defineLazyGetter( lazy, "WeaveService", ===================================== browser/components/about/AboutRedirector.cpp ===================================== @@ -166,13 +166,6 @@ static const RedirEntry kRedirMap[] = { nsIAboutModule::URI_MUST_LOAD_IN_CHILD | nsIAboutModule::ALLOW_SCRIPT | nsIAboutModule::URI_CAN_LOAD_IN_PRIVILEGEDABOUT_PROCESS | nsIAboutModule::HIDE_FROM_ABOUTABOUT}, -#ifdef BASE_BROWSER_UPDATE - {"tbupdate", "chrome://browser/content/abouttbupdate/aboutTBUpdate.xhtml", - nsIAboutModule::URI_SAFE_FOR_UNTRUSTED_CONTENT | - nsIAboutModule::URI_MUST_LOAD_IN_CHILD | nsIAboutModule::ALLOW_SCRIPT | - nsIAboutModule::HIDE_FROM_ABOUTABOUT | - nsIAboutModule::IS_SECURE_CHROME_UI}, -#endif // The correct URI must be obtained by GetManualChromeURI {"manual", "about:blank", nsIAboutModule::URI_SAFE_FOR_UNTRUSTED_CONTENT | ===================================== browser/components/about/components.conf ===================================== @@ -35,9 +35,6 @@ pages = [ 'welcomeback', ] -if defined('BASE_BROWSER_UPDATE'): - pages.append('tbupdate') - Classes = [ { 'cid': '{7e4bb6ad-2fc4-4dc6-89ef-23e8e5ccf980}', ===================================== toolkit/modules/RemotePageAccessManager.sys.mjs ===================================== @@ -237,9 +237,6 @@ export let RemotePageAccessManager = { RPMAddMessageListener: ["*"], RPMRemoveMessageListener: ["*"], }, - "about:tbupdate": { - RPMSendQuery: ["FetchUpdateData"], - }, "about:torconnect": { RPMAddMessageListener: [ "torconnect:state-change", ===================================== toolkit/torbutton/chrome/locale/en-US/aboutTBUpdate.dtd deleted ===================================== @@ -1,18 +0,0 @@ -<!-- Copyright (c) 2022, 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/. --> - -<!ENTITY aboutTBUpdate.changelogTitle "Tor Browser Changelog"> -<!ENTITY aboutTBUpdate.version "Version"> -<!ENTITY aboutTBUpdate.releaseDate "Release Date"> -<!ENTITY aboutTBUpdate.releaseNotes "Release Notes"> -<!-- LOCALIZATION NOTE: the following entities are used to create the link to - - obtain more information about the latest update. - - The markup on the page looks like this: - - &aboutTBUpdate.linkPrefix;<a href="...">&aboutTBUpdate.linkLabel;</a>&aboutTBUpdate.linkSuffix; - - So, linkPrefix is what precedes the link, linkLabel is the link itself, - - and linkSuffix is a text after the link. --> -<!ENTITY aboutTBUpdate.linkPrefix "For the most up-to-date information about this release, "> -<!ENTITY aboutTBUpdate.linkLabel "visit our website"> -<!ENTITY aboutTBUpdate.linkSuffix "."> ===================================== toolkit/torbutton/jar.mn ===================================== @@ -7,8 +7,5 @@ torbutton.jar: # browser branding % override chrome://branding/locale/brand.properties chrome://torbutton/locale/brand.properties -# Strings for the about:tbupdate page -% override chrome://browser/locale/aboutTBUpdate.dtd chrome://torbutton/locale/aboutTBUpdate.dtd - % locale torbutton en-US %locale/en-US/ locale/en-US/ (chrome/locale/en-US/*) View it on GitLab: https://gitlab.torproject.org/tpo/applications/tor-browser/-/compare/50cede… -- View it on GitLab: https://gitlab.torproject.org/tpo/applications/tor-browser/-/compare/50cede… You're receiving this email because of your account on gitlab.torproject.org.
1 0
0 0
[Git][tpo/applications/tor-browser][base-browser-128.4.0esr-14.5-1] Bug 42739: Use the brand name for profile error messages.
by morgan (@morgan) 30 Oct '24

30 Oct '24
morgan pushed to branch base-browser-128.4.0esr-14.5-1 at The Tor Project / Applications / Tor Browser Commits: b64a2539 by Henry Wilkes at 2024-10-29T20:48:07+00:00 Bug 42739: Use the brand name for profile error messages. Some messages in profileSelection.properties use gAppData-&gt;name as variable inputs. However, gAppData-&gt;name is still &quot;Firefox&quot; for our base-browser builds, rather than the user-facing browser name. We swap these instances with the displayed brand name instead. - - - - - 2 changed files: - toolkit/xre/ProfileReset.cpp - toolkit/xre/nsAppRunner.cpp Changes: ===================================== toolkit/xre/ProfileReset.cpp ===================================== @@ -23,8 +23,8 @@ using namespace mozilla; -extern const XREAppData* gAppData; - +static const char kBrandProperties[] = + "chrome://branding/locale/brand.properties"; static const char kProfileProperties[] = "chrome://mozapps/locale/profile/profileSelection.properties"; @@ -49,12 +49,21 @@ nsresult ProfileResetCleanup(nsToolkitProfileService* aService, mozilla::components::StringBundle::Service(); if (!sbs) return NS_ERROR_FAILURE; + nsCOMPtr<nsIStringBundle> brandBundle; + Unused << sbs->CreateBundle(kBrandProperties, getter_AddRefs(brandBundle)); + if (!brandBundle) return NS_ERROR_FAILURE; + nsCOMPtr<nsIStringBundle> sb; Unused << sbs->CreateBundle(kProfileProperties, getter_AddRefs(sb)); if (!sb) return NS_ERROR_FAILURE; - NS_ConvertUTF8toUTF16 appName(gAppData->name); - AutoTArray<nsString, 2> params = {appName, appName}; + nsAutoString appName; + rv = brandBundle->GetStringFromName("brandShortName", appName); + if (NS_FAILED(rv)) return rv; + + AutoTArray<nsString, 2> params; + params.AppendElement(appName); + params.AppendElement(appName); nsAutoString resetBackupDirectoryName; ===================================== toolkit/xre/nsAppRunner.cpp ===================================== @@ -2597,6 +2597,8 @@ nsresult LaunchChild(bool aBlankCommandLine, bool aTryExec) { return NS_ERROR_LAUNCHED_CHILD_PROCESS; } +static const char kBrandProperties[] = + "chrome://branding/locale/brand.properties"; static const char kProfileProperties[] = "chrome://mozapps/locale/profile/profileSelection.properties"; @@ -2666,12 +2668,20 @@ static nsresult ProfileMissingDialog(nsINativeAppSupport* aNative) { mozilla::components::StringBundle::Service(); NS_ENSURE_TRUE(sbs, NS_ERROR_FAILURE); + nsCOMPtr<nsIStringBundle> brandBundle; + sbs->CreateBundle(kBrandProperties, getter_AddRefs(brandBundle)); + NS_ENSURE_TRUE_LOG(sbs, NS_ERROR_FAILURE); nsCOMPtr<nsIStringBundle> sb; sbs->CreateBundle(kProfileProperties, getter_AddRefs(sb)); NS_ENSURE_TRUE_LOG(sbs, NS_ERROR_FAILURE); - NS_ConvertUTF8toUTF16 appName(gAppData->name); - AutoTArray<nsString, 2> params = {appName, appName}; + nsAutoString appName; + rv = brandBundle->GetStringFromName("brandShortName", appName); + NS_ENSURE_SUCCESS(rv, NS_ERROR_ABORT); + + AutoTArray<nsString, 2> params; + params.AppendElement(appName); + params.AppendElement(appName); // profileMissing nsAutoString missingMessage; @@ -2733,12 +2743,21 @@ static ReturnAbortOnError ProfileLockedDialog(nsIFile* aProfileDir, mozilla::components::StringBundle::Service(); NS_ENSURE_TRUE(sbs, NS_ERROR_FAILURE); + nsCOMPtr<nsIStringBundle> brandBundle; + sbs->CreateBundle(kBrandProperties, getter_AddRefs(brandBundle)); + NS_ENSURE_TRUE_LOG(sbs, NS_ERROR_FAILURE); nsCOMPtr<nsIStringBundle> sb; sbs->CreateBundle(kProfileProperties, getter_AddRefs(sb)); NS_ENSURE_TRUE_LOG(sbs, NS_ERROR_FAILURE); - NS_ConvertUTF8toUTF16 appName(gAppData->name); - AutoTArray<nsString, 3> params = {appName, appName, appName}; + nsAutoString appName; + rv = brandBundle->GetStringFromName("brandShortName", appName); + NS_ENSURE_SUCCESS(rv, NS_ERROR_ABORT); + + AutoTArray<nsString, 3> params; + params.AppendElement(appName); + params.AppendElement(appName); + params.AppendElement(appName); nsAutoString killMessage; #ifndef XP_MACOSX View it on GitLab: https://gitlab.torproject.org/tpo/applications/tor-browser/-/commit/b64a253… -- View it on GitLab: https://gitlab.torproject.org/tpo/applications/tor-browser/-/commit/b64a253… You're receiving this email because of your account on gitlab.torproject.org.
1 0
0 0
[Git][tpo/applications/tor-browser][tor-browser-128.4.0esr-14.5-1] 3 commits: fixup! Bug 14631: Improve profile access error messages.
by morgan (@morgan) 30 Oct '24

30 Oct '24
morgan pushed to branch tor-browser-128.4.0esr-14.5-1 at The Tor Project / Applications / Tor Browser Commits: 1f0bfac8 by Henry Wilkes at 2024-10-29T20:11:45+00:00 fixup! Bug 14631: Improve profile access error messages. Bug 42739: Revert patch for &quot;Improve profile access error messages.&quot; - - - - - 8cef0b28 by Henry Wilkes at 2024-10-29T20:11:45+00:00 fixup! Add TorStrings module for localization Bug 42739: Drop profile access error strings. - - - - - 50cede2a by Henry Wilkes at 2024-10-29T20:11:45+00:00 Bug 42739: Use the brand name for profile error messages. Some messages in profileSelection.properties use gAppData-&gt;name as variable inputs. However, gAppData-&gt;name is still &quot;Firefox&quot; for our base-browser builds, rather than the user-facing browser name. We swap these instances with the displayed brand name instead. - - - - - 6 changed files: - toolkit/locales/en-US/chrome/mozapps/profile/profileSelection.properties - toolkit/profile/nsToolkitProfileService.cpp - toolkit/profile/nsToolkitProfileService.h - − toolkit/torbutton/chrome/locale/en-US/torbutton.properties - toolkit/xre/ProfileReset.cpp - toolkit/xre/nsAppRunner.cpp Changes: ===================================== toolkit/locales/en-US/chrome/mozapps/profile/profileSelection.properties ===================================== @@ -12,11 +12,6 @@ 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’ ===================================== toolkit/profile/nsToolkitProfileService.cpp ===================================== @@ -1261,10 +1261,9 @@ nsToolkitProfileService::SelectStartupProfile( } bool wasDefault; - ProfileStatus profileStatus; nsresult rv = SelectStartupProfile(&argc, argv.get(), aIsResetting, aRootDir, aLocalDir, - aProfile, aDidCreate, &wasDefault, profileStatus); + aProfile, aDidCreate, &wasDefault); // Since we were called outside of the normal startup path complete any // startup tasks. @@ -1299,8 +1298,7 @@ static void SaltProfileName(nsACString& aName); nsresult nsToolkitProfileService::SelectStartupProfile( int* aArgc, char* aArgv[], bool aIsResetting, nsIFile** aRootDir, nsIFile** aLocalDir, nsIToolkitProfile** aProfile, bool* aDidCreate, - bool* aWasDefaultSelection, ProfileStatus& aProfileStatus) { - aProfileStatus = PROFILE_STATUS_OK; + bool* aWasDefaultSelection) { if (mStartupProfileSelected) { return NS_ERROR_ALREADY_INITIALIZED; } @@ -1393,13 +1391,6 @@ 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); @@ -2259,47 +2250,3 @@ 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) - constexpr auto writeTestFileName = u".parentwritetest"_ns; -#else - constexpr auto writeTestFileName = u"parent.writetest"_ns; -#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); -} ===================================== toolkit/profile/nsToolkitProfileService.h ===================================== @@ -17,14 +17,6 @@ #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>> { @@ -81,13 +73,10 @@ class nsToolkitProfileService final : public nsIToolkitProfileService { nsresult SelectStartupProfile(int* aArgc, char* aArgv[], bool aIsResetting, nsIFile** aRootDir, nsIFile** aLocalDir, nsIToolkitProfile** aProfile, bool* aDidCreate, - bool* aWasDefaultSelection, - ProfileStatus& aProfileStatus); + bool* aWasDefaultSelection); nsresult CreateResetProfile(nsIToolkitProfile** aNewProfile); nsresult ApplyResetProfile(nsIToolkitProfile* aOldProfile); void CompleteStartup(); - static ProfileStatus CheckProfileWriteAccess(nsIToolkitProfile* aProfile); - static ProfileStatus CheckProfileWriteAccess(nsIFile* aProfileDir); private: friend class nsToolkitProfile; ===================================== toolkit/torbutton/chrome/locale/en-US/torbutton.properties deleted ===================================== @@ -1,11 +0,0 @@ -# Copyright (c) 2022, 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/. - -# Profile/startup error messages. -# LOCALIZATION NOTE: %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. ===================================== toolkit/xre/ProfileReset.cpp ===================================== @@ -23,8 +23,8 @@ using namespace mozilla; -extern const XREAppData* gAppData; - +static const char kBrandProperties[] = + "chrome://branding/locale/brand.properties"; static const char kProfileProperties[] = "chrome://mozapps/locale/profile/profileSelection.properties"; @@ -49,12 +49,21 @@ nsresult ProfileResetCleanup(nsToolkitProfileService* aService, mozilla::components::StringBundle::Service(); if (!sbs) return NS_ERROR_FAILURE; + nsCOMPtr<nsIStringBundle> brandBundle; + Unused << sbs->CreateBundle(kBrandProperties, getter_AddRefs(brandBundle)); + if (!brandBundle) return NS_ERROR_FAILURE; + nsCOMPtr<nsIStringBundle> sb; Unused << sbs->CreateBundle(kProfileProperties, getter_AddRefs(sb)); if (!sb) return NS_ERROR_FAILURE; - NS_ConvertUTF8toUTF16 appName(gAppData->name); - AutoTArray<nsString, 2> params = {appName, appName}; + nsAutoString appName; + rv = brandBundle->GetStringFromName("brandShortName", appName); + if (NS_FAILED(rv)) return rv; + + AutoTArray<nsString, 2> params; + params.AppendElement(appName); + params.AppendElement(appName); nsAutoString resetBackupDirectoryName; ===================================== toolkit/xre/nsAppRunner.cpp ===================================== @@ -2599,91 +2599,8 @@ nsresult LaunchChild(bool aBlankCommandLine, bool aTryExec) { 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 kBrandProperties[] = + "chrome://branding/locale/brand.properties"; static const char kProfileProperties[] = "chrome://mozapps/locale/profile/profileSelection.properties"; @@ -2753,12 +2670,20 @@ static nsresult ProfileMissingDialog(nsINativeAppSupport* aNative) { mozilla::components::StringBundle::Service(); NS_ENSURE_TRUE(sbs, NS_ERROR_FAILURE); + nsCOMPtr<nsIStringBundle> brandBundle; + sbs->CreateBundle(kBrandProperties, getter_AddRefs(brandBundle)); + NS_ENSURE_TRUE_LOG(sbs, NS_ERROR_FAILURE); nsCOMPtr<nsIStringBundle> sb; sbs->CreateBundle(kProfileProperties, getter_AddRefs(sb)); NS_ENSURE_TRUE_LOG(sbs, NS_ERROR_FAILURE); - NS_ConvertUTF8toUTF16 appName(MOZ_APP_DISPLAYNAME); - AutoTArray<nsString, 2> params = {appName, appName}; + nsAutoString appName; + rv = brandBundle->GetStringFromName("brandShortName", appName); + NS_ENSURE_SUCCESS(rv, NS_ERROR_ABORT); + + AutoTArray<nsString, 2> params; + params.AppendElement(appName); + params.AppendElement(appName); // profileMissing nsAutoString missingMessage; @@ -2782,12 +2707,11 @@ 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, - nsIProfileUnlocker* aUnlocker, - nsINativeAppSupport* aNative, - nsIProfileLock** aResult) { +static ReturnAbortOnError ProfileLockedDialog(nsIFile* aProfileDir, + nsIFile* aProfileLocalDir, + nsIProfileUnlocker* aUnlocker, + nsINativeAppSupport* aNative, + nsIProfileLock** aResult) { nsresult rv; if (aProfileDir) { @@ -2821,43 +2745,37 @@ static ReturnAbortOnError ProfileErrorDialog(nsIFile* aProfileDir, mozilla::components::StringBundle::Service(); NS_ENSURE_TRUE(sbs, NS_ERROR_FAILURE); + nsCOMPtr<nsIStringBundle> brandBundle; + sbs->CreateBundle(kBrandProperties, getter_AddRefs(brandBundle)); + NS_ENSURE_TRUE_LOG(sbs, NS_ERROR_FAILURE); nsCOMPtr<nsIStringBundle> sb; sbs->CreateBundle(kProfileProperties, getter_AddRefs(sb)); NS_ENSURE_TRUE_LOG(sbs, NS_ERROR_FAILURE); - nsCOMPtr<nsIStringBundle> overrideSB; - GetOverrideStringBundle(sbs, getter_AddRefs(overrideSB)); + nsAutoString appName; + rv = brandBundle->GetStringFromName("brandShortName", appName); + NS_ENSURE_SUCCESS(rv, NS_ERROR_ABORT); - NS_ConvertUTF8toUTF16 appName(MOZ_APP_DISPLAYNAME); - AutoTArray<nsString, 3> params = {appName, appName, appName}; + AutoTArray<nsString, 3> params; + params.AppendElement(appName); + params.AppendElement(appName); + params.AppendElement(appName); nsAutoString killMessage; #ifndef XP_MACOSX - static const char kRestartUnlocker[] = "restartMessageUnlocker"; - static const char kRestartNoUnlocker[] = "restartMessageNoUnlocker2"; - static const char kReadOnly[] = "profileReadOnly"; + rv = sb->FormatStringFromName( + aUnlocker ? "restartMessageUnlocker" : "restartMessageNoUnlocker2", + params, killMessage); #else - 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); + rv = sb->FormatStringFromName( + aUnlocker ? "restartMessageUnlockerMac" : "restartMessageNoUnlockerMac", + params, killMessage); +#endif 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(titleKey, params, killTitle); + rv = sb->FormatStringFromName("restartTitle", params, killTitle); NS_ENSURE_SUCCESS(rv, NS_ERROR_FAILURE); #ifdef MOZ_BACKGROUNDTASKS @@ -3028,24 +2946,6 @@ static ReturnAbortOnError ShowProfileManager( return LaunchChild(false, true); } -#ifdef XP_MACOSX -static ProfileStatus CheckTorBrowserDataWriteAccess() { - // Check whether we can write to the directory that will contain - // TorBrowser-Data. - RefPtr<nsXREDirProvider> singleton = nsXREDirProvider::GetSingleton(); - if (!singleton) { - return PROFILE_STATUS_OTHER_ERROR; - } - nsCOMPtr<nsIFile> tbDataDir; - nsresult rv = singleton->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; @@ -3053,13 +2953,6 @@ 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 @@ -3086,8 +2979,7 @@ static nsresult LockProfile(nsINativeAppSupport* aNative, nsIFile* aRootDir, } while (TimeStamp::Now() - start < TimeDuration::FromSeconds(kLockRetrySeconds)); - return ProfileErrorDialog(aRootDir, aLocalDir, PROFILE_STATUS_IS_LOCKED, - unlocker, aNative, aResult); + return ProfileLockedDialog(aRootDir, aLocalDir, unlocker, aNative, aResult); } // Pick a profile. We need to end up with a profile root dir, local dir and @@ -3102,8 +2994,7 @@ static nsresult LockProfile(nsINativeAppSupport* aNative, nsIFile* aRootDir, static nsresult SelectProfile(nsToolkitProfileService* aProfileSvc, nsINativeAppSupport* aNative, nsIFile** aRootDir, nsIFile** aLocalDir, nsIToolkitProfile** aProfile, - bool* aWasDefaultSelection, - nsIProfileLock** aResult) { + bool* aWasDefaultSelection) { StartupTimeline::Record(StartupTimeline::SELECT_PROFILE); nsresult rv; @@ -3141,14 +3032,9 @@ static nsresult SelectProfile(nsToolkitProfileService* aProfileSvc, // Ask the profile manager to select the profile directories to use. bool didCreate = false; - 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); - } + rv = aProfileSvc->SelectStartupProfile(&gArgc, gArgv, gDoProfileReset, + aRootDir, aLocalDir, aProfile, + &didCreate, aWasDefaultSelection); if (rv == NS_ERROR_SHOW_PROFILE_MANAGER) { return ShowProfileManager(aProfileSvc, aNative); @@ -5062,19 +4948,6 @@ int XREMain::XRE_mainStartup(bool* aExitFlag) { mProfileSvc = NS_GetToolkitProfileService(); if (!mProfileSvc) { -#ifdef XP_MACOSX - // 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(); - if ((PROFILE_STATUS_ACCESS_DENIED == status) || - (PROFILE_STATUS_READ_ONLY == status)) { - ProfileErrorDialog(nullptr, nullptr, status, nullptr, mNativeApp, - nullptr); - return 1; - } -#endif // We failed to choose or create profile - notify user and quit ProfileMissingDialog(mNativeApp); return 1; @@ -5084,7 +4957,7 @@ int XREMain::XRE_mainStartup(bool* aExitFlag) { nsCOMPtr<nsIToolkitProfile> profile; rv = SelectProfile(mProfileSvc, mNativeApp, getter_AddRefs(mProfD), getter_AddRefs(mProfLD), getter_AddRefs(profile), - &wasDefaultSelection, getter_AddRefs(mProfileLock)); + &wasDefaultSelection); if (rv == NS_ERROR_LAUNCHED_CHILD_PROCESS || rv == NS_ERROR_ABORT) { *aExitFlag = true; return 0; View it on GitLab: https://gitlab.torproject.org/tpo/applications/tor-browser/-/compare/464b5a… -- View it on GitLab: https://gitlab.torproject.org/tpo/applications/tor-browser/-/compare/464b5a… You're receiving this email because of your account on gitlab.torproject.org.
1 0
0 0
[Git][tpo/applications/tor-browser-build][main] Update release prep merge request template
by morgan (@morgan) 30 Oct '24

30 Oct '24
morgan pushed to branch main at The Tor Project / Applications / tor-browser-build Commits: 0178b624 by Nicolas Vigier at 2024-10-29T20:08:40+00:00 Update release prep merge request template Update self-review template to add torbrowser_legacy vars to rbm.conf, and remove firefox-android. - - - - - 1 changed file: - .gitlab/merge_request_templates/relprep.md Changes: ===================================== .gitlab/merge_request_templates/relprep.md ===================================== @@ -10,10 +10,11 @@ - [ ] `var/torbrowser_build`: should be `build1`, unless bumping a previous release preparation - [ ] `var/browser_release_date`: must not be in the future when we start building - [ ] `var/torbrowser_incremental_from` (not needed for Android-only releases) + - [ ] `var/torbrowser_legacy_version` (For Tor Browser 14.0.x stable releases only) + - [ ] `var/torbrowser_legacy_platform_version` (For Tor Browser 14.0.x stable releases only) - [ ] Tag updates: - [ ] [Firefox](https://gitlab.torproject.org/tpo/applications/tor-browser/-/tags) - [ ] Geckoview - should match Firefox - - [ ] [Firefox Android](https://gitlab.torproject.org/tpo/applications/firefox-android/-/t… - Tags might be speculative in the release preparation: i.e., they might not exist yet. - [ ] Addon updates: - [ ] [NoScript](https://addons.mozilla.org/en-US/firefox/addon/noscript/) View it on GitLab: https://gitlab.torproject.org/tpo/applications/tor-browser-build/-/commit/0… -- View it on GitLab: https://gitlab.torproject.org/tpo/applications/tor-browser-build/-/commit/0… You're receiving this email because of your account on gitlab.torproject.org.
1 0
0 0
[Git][tpo/applications/mullvad-browser][mullvad-browser-128.4.0esr-14.5-1] 2 commits: fixup! Bug 40283: Workaround for the file upload bug
by Pier Angelo Vendrame (@pierov) 29 Oct '24

29 Oct '24
Pier Angelo Vendrame pushed to branch mullvad-browser-128.4.0esr-14.5-1 at The Tor Project / Applications / Mullvad Browser Commits: 1eb1dd23 by Pier Angelo Vendrame at 2024-10-29T19:10:13+01:00 fixup! Bug 40283: Workaround for the file upload bug Lint with android-format. - - - - - 291acbab by Pier Angelo Vendrame at 2024-10-29T19:10:21+01:00 fixup! Bug 40171: Make WebRequest and GeckoWebExecutor First-Party aware Lint with android-format. - - - - - 2 changed files: - mobile/android/geckoview/src/main/java/org/mozilla/geckoview/GeckoSession.java - mobile/android/geckoview/src/main/java/org/mozilla/geckoview/WebRequest.java Changes: ===================================== mobile/android/geckoview/src/main/java/org/mozilla/geckoview/GeckoSession.java ===================================== @@ -6301,10 +6301,10 @@ public class GeckoSession { } private static String normalizePath(String input) { - // For an unclear reason, Android media picker delivers file paths - // starting with double slash. Firefox performs path validation on - // all paths, and double slash is deemed invalid. - return input.startsWith("//") ? input.substring(1) : input; + // For an unclear reason, Android media picker delivers file paths + // starting with double slash. Firefox performs path validation on + // all paths, and double slash is deemed invalid. + return input.startsWith("//") ? input.substring(1) : input; } private static String getFile(final @NonNull Context context, final @NonNull Uri uri) { ===================================== mobile/android/geckoview/src/main/java/org/mozilla/geckoview/WebRequest.java ===================================== @@ -49,9 +49,7 @@ public class WebRequest extends WebMessage { /** The value of the Referer header for this request. */ public final @Nullable String referrer; - /** - * The value of the origin of this request. - */ + /** The value of the origin of this request. */ public final @Nullable String origin; @Retention(RetentionPolicy.SOURCE) @@ -248,10 +246,10 @@ public class WebRequest extends WebMessage { * @param origin A URI String * @return This Builder instance. */ - public @NonNull Builder origin(final @Nullable String origin) { - mOrigin = origin; - return this; - } + public @NonNull Builder origin(final @Nullable String origin) { + mOrigin = origin; + return this; + } /** * @return A {@link WebRequest} constructed with the values from this Builder instance. View it on GitLab: https://gitlab.torproject.org/tpo/applications/mullvad-browser/-/compare/4e… -- View it on GitLab: https://gitlab.torproject.org/tpo/applications/mullvad-browser/-/compare/4e… You're receiving this email because of your account on gitlab.torproject.org.
1 0
0 0
[Git][tpo/applications/tor-browser][base-browser-128.4.0esr-14.5-1] 2 commits: fixup! Bug 40283: Workaround for the file upload bug
by Pier Angelo Vendrame (@pierov) 29 Oct '24

29 Oct '24
Pier Angelo Vendrame pushed to branch base-browser-128.4.0esr-14.5-1 at The Tor Project / Applications / Tor Browser Commits: 4b20df89 by Pier Angelo Vendrame at 2024-10-29T19:08:47+01:00 fixup! Bug 40283: Workaround for the file upload bug Lint with android-format. - - - - - 8cd93211 by Pier Angelo Vendrame at 2024-10-29T19:08:54+01:00 fixup! Bug 40171: Make WebRequest and GeckoWebExecutor First-Party aware Lint with android-format. - - - - - 2 changed files: - mobile/android/geckoview/src/main/java/org/mozilla/geckoview/GeckoSession.java - mobile/android/geckoview/src/main/java/org/mozilla/geckoview/WebRequest.java Changes: ===================================== mobile/android/geckoview/src/main/java/org/mozilla/geckoview/GeckoSession.java ===================================== @@ -6301,10 +6301,10 @@ public class GeckoSession { } private static String normalizePath(String input) { - // For an unclear reason, Android media picker delivers file paths - // starting with double slash. Firefox performs path validation on - // all paths, and double slash is deemed invalid. - return input.startsWith("//") ? input.substring(1) : input; + // For an unclear reason, Android media picker delivers file paths + // starting with double slash. Firefox performs path validation on + // all paths, and double slash is deemed invalid. + return input.startsWith("//") ? input.substring(1) : input; } private static String getFile(final @NonNull Context context, final @NonNull Uri uri) { ===================================== mobile/android/geckoview/src/main/java/org/mozilla/geckoview/WebRequest.java ===================================== @@ -49,9 +49,7 @@ public class WebRequest extends WebMessage { /** The value of the Referer header for this request. */ public final @Nullable String referrer; - /** - * The value of the origin of this request. - */ + /** The value of the origin of this request. */ public final @Nullable String origin; @Retention(RetentionPolicy.SOURCE) @@ -248,10 +246,10 @@ public class WebRequest extends WebMessage { * @param origin A URI String * @return This Builder instance. */ - public @NonNull Builder origin(final @Nullable String origin) { - mOrigin = origin; - return this; - } + public @NonNull Builder origin(final @Nullable String origin) { + mOrigin = origin; + return this; + } /** * @return A {@link WebRequest} constructed with the values from this Builder instance. View it on GitLab: https://gitlab.torproject.org/tpo/applications/tor-browser/-/compare/3975e7… -- View it on GitLab: https://gitlab.torproject.org/tpo/applications/tor-browser/-/compare/3975e7… You're receiving this email because of your account on gitlab.torproject.org.
1 0
0 0
[Git][tpo/applications/tor-browser][tor-browser-128.4.0esr-14.5-1] 6 commits: fixup! Bug 40283: Workaround for the file upload bug
by Pier Angelo Vendrame (@pierov) 29 Oct '24

29 Oct '24
Pier Angelo Vendrame pushed to branch tor-browser-128.4.0esr-14.5-1 at The Tor Project / Applications / Tor Browser Commits: 41bcfa1b by Pier Angelo Vendrame at 2024-10-29T19:05:48+01:00 fixup! Bug 40283: Workaround for the file upload bug Lint with android-format. - - - - - c8428799 by Pier Angelo Vendrame at 2024-10-29T19:05:53+01:00 fixup! Bug 40171: Make WebRequest and GeckoWebExecutor First-Party aware Lint with android-format. - - - - - cdcb77db by Pier Angelo Vendrame at 2024-10-29T19:05:53+01:00 fixup! Bug 42247: Android helpers for the TorProvider Lint with android-format. - - - - - ad0782df by Pier Angelo Vendrame at 2024-10-29T19:05:54+01:00 fixup! Bug 40597: Implement TorSettings module Fix a couple of references to Moat in the generic DomainFrontedRequests module. - - - - - 6b2120f9 by Pier Angelo Vendrame at 2024-10-29T19:05:54+01:00 fixup! Bug 40597: Implement TorSettings module ch.asyncOpen is not a JS async function, so no need to await it. The async in the name means that the channel will call methods from a listener object that it takes as an argument when it receives data. - - - - - 464b5a9b by Pier Angelo Vendrame at 2024-10-29T19:05:55+01:00 fixup! Bug 42247: Android helpers for the TorProvider Bug 43232: Make the Android Meek transport easier to debug. - - - - - 8 changed files: - mobile/android/geckoview/src/main/java/org/mozilla/geckoview/GeckoSession.java - mobile/android/geckoview/src/main/java/org/mozilla/geckoview/TorIntegrationAndroid.java - mobile/android/geckoview/src/main/java/org/mozilla/geckoview/TorSettings.java - mobile/android/geckoview/src/main/java/org/mozilla/geckoview/WebRequest.java - mobile/android/geckoview/src/main/java/org/mozilla/geckoview/androidlegacysettings/Prefs.java - mobile/android/geckoview/src/main/java/org/mozilla/geckoview/androidlegacysettings/TorLegacyAndroidSettings.java - toolkit/modules/DomainFrontedRequests.sys.mjs - toolkit/modules/Moat.sys.mjs Changes: ===================================== mobile/android/geckoview/src/main/java/org/mozilla/geckoview/GeckoSession.java ===================================== @@ -6319,10 +6319,10 @@ public class GeckoSession { } private static String normalizePath(String input) { - // For an unclear reason, Android media picker delivers file paths - // starting with double slash. Firefox performs path validation on - // all paths, and double slash is deemed invalid. - return input.startsWith("//") ? input.substring(1) : input; + // For an unclear reason, Android media picker delivers file paths + // starting with double slash. Firefox performs path validation on + // all paths, and double slash is deemed invalid. + return input.startsWith("//") ? input.substring(1) : input; } private static String getFile(final @NonNull Context context, final @NonNull Uri uri) { ===================================== mobile/android/geckoview/src/main/java/org/mozilla/geckoview/TorIntegrationAndroid.java ===================================== @@ -9,671 +9,720 @@ package org.mozilla.geckoview; import android.content.Context; import android.os.AsyncTask; import android.util.Log; - -import androidx.annotation.AnyThread; import androidx.annotation.NonNull; -import androidx.annotation.Nullable; - import java.io.BufferedReader; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; +import java.io.InterruptedIOException; import java.util.ArrayList; +import java.util.Arrays; import java.util.HashMap; import java.util.HashSet; import java.util.Map; -import java.util.Set; - import org.mozilla.gecko.EventDispatcher; import org.mozilla.gecko.GeckoAppShell; import org.mozilla.gecko.util.BundleEventListener; import org.mozilla.gecko.util.EventCallback; import org.mozilla.gecko.util.GeckoBundle; - import org.mozilla.geckoview.androidlegacysettings.TorLegacyAndroidSettings; public class TorIntegrationAndroid implements BundleEventListener { - private static final String TAG = "TorIntegrationAndroid"; - - // Events we listen to - private static final String EVENT_TOR_START = "GeckoView:Tor:StartTor"; - private static final String EVENT_TOR_STOP = "GeckoView:Tor:StopTor"; - private static final String EVENT_MEEK_START = "GeckoView:Tor:StartMeek"; - private static final String EVENT_MEEK_STOP = "GeckoView:Tor:StopMeek"; - private static final String EVENT_CONNECT_STATE_CHANGED = "GeckoView:Tor:ConnectStateChanged"; - private static final String EVENT_CONNECT_ERROR = "GeckoView:Tor:ConnectError"; - private static final String EVENT_BOOTSTRAP_PROGRESS = "GeckoView:Tor:BootstrapProgress"; - private static final String EVENT_BOOTSTRAP_COMPLETE = "GeckoView:Tor:BootstrapComplete"; - private static final String EVENT_TOR_LOGS = "GeckoView:Tor:Logs"; - private static final String EVENT_SETTINGS_READY = "GeckoView:Tor:SettingsReady"; - private static final String EVENT_SETTINGS_CHANGED = "GeckoView:Tor:SettingsChanged"; - private static final String EVENT_SETTINGS_OPEN = "GeckoView:Tor:OpenSettings"; - - // Events we emit - private static final String EVENT_SETTINGS_GET = "GeckoView:Tor:SettingsGet"; - private static final String EVENT_SETTINGS_SET = "GeckoView:Tor:SettingsSet"; - private static final String EVENT_SETTINGS_APPLY = "GeckoView:Tor:SettingsApply"; - private static final String EVENT_SETTINGS_SAVE = "GeckoView:Tor:SettingsSave"; - private static final String EVENT_BOOTSTRAP_BEGIN = "GeckoView:Tor:BootstrapBegin"; - private static final String EVENT_BOOTSTRAP_BEGIN_AUTO = "GeckoView:Tor:BootstrapBeginAuto"; - private static final String EVENT_BOOTSTRAP_CANCEL = "GeckoView:Tor:BootstrapCancel"; - private static final String EVENT_BOOTSTRAP_GET_STATE = "GeckoView:Tor:BootstrapGetState"; - - private static final String CONTROL_PORT_FILE = "/control-ipc"; - private static final String SOCKS_FILE = "/socks-ipc"; - private static final String COOKIE_AUTH_FILE = "/auth-file"; - - private final String mLibraryDir; - private final String mCacheDir; - private final String mIpcDirectory; - private final File mDataDir; - - private TorProcess mTorProcess = null; - /** - * The first time we run a Tor process in this session, we copy some configuration files to be - * sure we always have the latest version, but if we re-launch a tor process we do not need to - * copy them again. - */ - private boolean mCopiedConfigFiles = false; - /** - * Allow multiple proxies to be started, even though it might not actually happen. - * The key should be positive (also 0 is not allowed). - */ - private final HashMap<Integer, MeekTransport> mMeeks = new HashMap<>(); - private int mMeekCounter; - - /** - * mSettings is a Java-side copy of the authoritative settings in the JS code. - * It's useful to maintain as the UI may be fetching these options often and we don't watch each - * fetch to be a passthrough to JS with marshalling/unmarshalling each time. - */ - private TorSettings mSettings = null; - - /* package */ TorIntegrationAndroid(Context context) { - mLibraryDir = context.getApplicationInfo().nativeLibraryDir; - mCacheDir = context.getCacheDir().getAbsolutePath(); - mIpcDirectory = mCacheDir + "/tor-private"; - mDataDir = new File(context.getFilesDir(), "tor"); - registerListener(); + private static final String TAG = "TorIntegrationAndroid"; + + // Events we listen to + private static final String EVENT_TOR_START = "GeckoView:Tor:StartTor"; + private static final String EVENT_TOR_STOP = "GeckoView:Tor:StopTor"; + private static final String EVENT_MEEK_START = "GeckoView:Tor:StartMeek"; + private static final String EVENT_MEEK_STOP = "GeckoView:Tor:StopMeek"; + private static final String EVENT_CONNECT_STATE_CHANGED = "GeckoView:Tor:ConnectStateChanged"; + private static final String EVENT_CONNECT_ERROR = "GeckoView:Tor:ConnectError"; + private static final String EVENT_BOOTSTRAP_PROGRESS = "GeckoView:Tor:BootstrapProgress"; + private static final String EVENT_BOOTSTRAP_COMPLETE = "GeckoView:Tor:BootstrapComplete"; + private static final String EVENT_TOR_LOGS = "GeckoView:Tor:Logs"; + private static final String EVENT_SETTINGS_READY = "GeckoView:Tor:SettingsReady"; + private static final String EVENT_SETTINGS_CHANGED = "GeckoView:Tor:SettingsChanged"; + private static final String EVENT_SETTINGS_OPEN = "GeckoView:Tor:OpenSettings"; + + // Events we emit + private static final String EVENT_SETTINGS_GET = "GeckoView:Tor:SettingsGet"; + private static final String EVENT_SETTINGS_SET = "GeckoView:Tor:SettingsSet"; + private static final String EVENT_SETTINGS_APPLY = "GeckoView:Tor:SettingsApply"; + private static final String EVENT_SETTINGS_SAVE = "GeckoView:Tor:SettingsSave"; + private static final String EVENT_BOOTSTRAP_BEGIN = "GeckoView:Tor:BootstrapBegin"; + private static final String EVENT_BOOTSTRAP_BEGIN_AUTO = "GeckoView:Tor:BootstrapBeginAuto"; + private static final String EVENT_BOOTSTRAP_CANCEL = "GeckoView:Tor:BootstrapCancel"; + private static final String EVENT_BOOTSTRAP_GET_STATE = "GeckoView:Tor:BootstrapGetState"; + + private static final String CONTROL_PORT_FILE = "/control-ipc"; + private static final String SOCKS_FILE = "/socks-ipc"; + private static final String COOKIE_AUTH_FILE = "/auth-file"; + + private final String mLibraryDir; + private final String mCacheDir; + private final String mIpcDirectory; + private final File mDataDir; + + private TorProcess mTorProcess = null; + + /** + * The first time we run a Tor process in this session, we copy some configuration files to be + * sure we always have the latest version, but if we re-launch a tor process we do not need to + * copy them again. + */ + private boolean mCopiedConfigFiles = false; + + /** + * Allow multiple proxies to be started, even though it might not actually happen. The key should + * be positive (also 0 is not allowed). + */ + private final HashMap<Integer, MeekTransport> mMeeks = new HashMap<>(); + + private int mMeekCounter; + + /** + * mSettings is a Java-side copy of the authoritative settings in the JS code. It's useful to + * maintain as the UI may be fetching these options often and we don't watch each fetch to be a + * passthrough to JS with marshalling/unmarshalling each time. + */ + private TorSettings mSettings = null; + + /* package */ TorIntegrationAndroid(Context context) { + mLibraryDir = context.getApplicationInfo().nativeLibraryDir; + mCacheDir = context.getCacheDir().getAbsolutePath(); + mIpcDirectory = mCacheDir + "/tor-private"; + mDataDir = new File(context.getFilesDir(), "tor"); + registerListener(); + } + + /* package */ synchronized void shutdown() { + // FIXME: It seems this never gets called + if (mTorProcess != null) { + mTorProcess.shutdown(); + mTorProcess = null; } - - /* package */ synchronized void shutdown() { - // FIXME: It seems this never gets called - if (mTorProcess != null) { - mTorProcess.shutdown(); - mTorProcess = null; - } + } + + private void registerListener() { + EventDispatcher.getInstance() + .registerUiThreadListener( + this, + EVENT_TOR_START, + EVENT_MEEK_START, + EVENT_MEEK_STOP, + EVENT_SETTINGS_READY, + EVENT_SETTINGS_CHANGED, + EVENT_CONNECT_STATE_CHANGED, + EVENT_CONNECT_ERROR, + EVENT_BOOTSTRAP_PROGRESS, + EVENT_BOOTSTRAP_COMPLETE, + EVENT_TOR_LOGS, + EVENT_SETTINGS_OPEN); + } + + @Override // BundleEventListener + public synchronized void handleMessage( + final String event, final GeckoBundle message, final EventCallback callback) { + if (EVENT_TOR_START.equals(event)) { + startDaemon(message, callback); + } else if (EVENT_TOR_STOP.equals(event)) { + stopDaemon(message, callback); + } else if (EVENT_MEEK_START.equals(event)) { + startMeek(message, callback); + } else if (EVENT_MEEK_STOP.equals(event)) { + stopMeek(message, callback); + } else if (EVENT_SETTINGS_READY.equals(event)) { + try { + new SettingsLoader().execute(message); + } catch (Exception e) { + Log.e(TAG, "SettingsLoader error: " + e.toString()); + } + } else if (EVENT_SETTINGS_CHANGED.equals(event)) { + GeckoBundle newSettings = message.getBundle("settings"); + if (newSettings != null) { + // TODO: Should we notify listeners? + mSettings = new TorSettings(newSettings); + } else { + Log.w(TAG, "Ignoring a settings changed event that did not have the new settings."); + } + } else if (EVENT_CONNECT_STATE_CHANGED.equals(event)) { + String state = message.getString("state"); + for (BootstrapStateChangeListener listener : mBootstrapStateListeners) { + listener.onBootstrapStateChange(state); + } + } else if (EVENT_CONNECT_ERROR.equals(event)) { + String code = message.getString("code"); + String msg = message.getString("message"); + String phase = message.getString("phase"); + String reason = message.getString("reason"); + for (BootstrapStateChangeListener listener : mBootstrapStateListeners) { + listener.onBootstrapError(code, msg, phase, reason); + } + } else if (EVENT_BOOTSTRAP_PROGRESS.equals(event)) { + double progress = message.getDouble("progress"); + boolean hasWarnings = message.getBoolean("hasWarnings"); + for (BootstrapStateChangeListener listener : mBootstrapStateListeners) { + listener.onBootstrapProgress(progress, hasWarnings); + } + } else if (EVENT_BOOTSTRAP_COMPLETE.equals(event)) { + for (BootstrapStateChangeListener listener : mBootstrapStateListeners) { + listener.onBootstrapComplete(); + } + } else if (EVENT_TOR_LOGS.equals(event)) { + String msg = message.getString("message"); + String type = message.getString("logType"); + for (TorLogListener listener : mLogListeners) { + listener.onLog(type, msg); + } + } else if (EVENT_SETTINGS_OPEN.equals(event)) { + for (BootstrapStateChangeListener listener : mBootstrapStateListeners) { + listener.onSettingsRequested(); + } } - - private void registerListener() { - EventDispatcher.getInstance() - .registerUiThreadListener( - this, - EVENT_TOR_START, - EVENT_MEEK_START, - EVENT_MEEK_STOP, - EVENT_SETTINGS_READY, - EVENT_SETTINGS_CHANGED, - EVENT_CONNECT_STATE_CHANGED, - EVENT_CONNECT_ERROR, - EVENT_BOOTSTRAP_PROGRESS, - EVENT_BOOTSTRAP_COMPLETE, - EVENT_TOR_LOGS, - EVENT_SETTINGS_OPEN); + } + + private class SettingsLoader extends AsyncTask<GeckoBundle, Void, TorSettings> { + protected TorSettings doInBackground(GeckoBundle... messages) { + GeckoBundle message = messages[0]; + TorSettings settings; + if (TorLegacyAndroidSettings.unmigrated()) { + settings = TorLegacyAndroidSettings.loadTorSettings(); + } else { + GeckoBundle bundle = message.getBundle("settings"); + settings = new TorSettings(bundle); + } + return settings; } - @Override // BundleEventListener - public synchronized void handleMessage( - final String event, final GeckoBundle message, final EventCallback callback) { - if (EVENT_TOR_START.equals(event)) { - startDaemon(message, callback); - } else if (EVENT_TOR_STOP.equals(event)) { - stopDaemon(message, callback); - } else if (EVENT_MEEK_START.equals(event)) { - startMeek(message, callback); - } else if (EVENT_MEEK_STOP.equals(event)) { - stopMeek(message, callback); - } else if (EVENT_SETTINGS_READY.equals(event)) { - try { - new SettingsLoader().execute(message); - } catch(Exception e) { - Log.e(TAG, "SettingsLoader error: "+ e.toString()); - } - } else if (EVENT_SETTINGS_CHANGED.equals(event)) { - GeckoBundle newSettings = message.getBundle("settings"); - if (newSettings != null) { - // TODO: Should we notify listeners? - mSettings = new TorSettings(newSettings); - } else { - Log.w(TAG, "Ignoring a settings changed event that did not have the new settings."); - } - } else if (EVENT_CONNECT_STATE_CHANGED.equals(event)) { - String state = message.getString("state"); - for (BootstrapStateChangeListener listener: mBootstrapStateListeners) { - listener.onBootstrapStateChange(state); - } - } else if (EVENT_CONNECT_ERROR.equals(event)) { - String code = message.getString("code"); - String msg = message.getString("message"); - String phase = message.getString("phase"); - String reason = message.getString("reason"); - for (BootstrapStateChangeListener listener: mBootstrapStateListeners) { - listener.onBootstrapError(code, msg, phase, reason); - } - } else if (EVENT_BOOTSTRAP_PROGRESS.equals(event)) { - double progress = message.getDouble("progress"); - boolean hasWarnings = message.getBoolean("hasWarnings"); - for (BootstrapStateChangeListener listener: mBootstrapStateListeners) { - listener.onBootstrapProgress(progress, hasWarnings); - } - } else if (EVENT_BOOTSTRAP_COMPLETE.equals(event)) { - for (BootstrapStateChangeListener listener: mBootstrapStateListeners) { - listener.onBootstrapComplete(); - } - } else if (EVENT_TOR_LOGS.equals(event)) { - String msg = message.getString("message"); - String type = message.getString("logType"); - for (TorLogListener listener: mLogListeners) { - listener.onLog(type, msg); - } - } else if (EVENT_SETTINGS_OPEN.equals(event)) { - for (BootstrapStateChangeListener listener: mBootstrapStateListeners) { - listener.onSettingsRequested(); - } - } + @Override + protected void onPostExecute(TorSettings torSettings) { + mSettings = torSettings; + if (TorLegacyAndroidSettings.unmigrated()) { + setSettings(mSettings, true, true); + TorLegacyAndroidSettings.setMigrated(); + } + } + } + + private synchronized void startDaemon(final GeckoBundle message, final EventCallback callback) { + // Let JS generate this to possibly reduce the chance of race conditions. + String handle = message.getString("handle", ""); + if (handle.isEmpty()) { + Log.e(TAG, "Requested to start a tor process without a handle."); + callback.sendError("Expected a handle for the new process."); + return; } + Log.d(TAG, "Starting the a tor process with handle " + handle); - private class SettingsLoader extends AsyncTask<GeckoBundle, Void, TorSettings> { - protected TorSettings doInBackground(GeckoBundle... messages) { - GeckoBundle message = messages[0]; - TorSettings settings; - if (TorLegacyAndroidSettings.unmigrated()) { - settings = TorLegacyAndroidSettings.loadTorSettings(); - } else { - GeckoBundle bundle = message.getBundle("settings"); - settings = new TorSettings(bundle); - } - return settings; - } + TorProcess previousProcess = mTorProcess; + if (previousProcess != null) { + Log.w(TAG, "We still have a running process: " + previousProcess.getHandle()); + } + mTorProcess = new TorProcess(handle); + + GeckoBundle bundle = new GeckoBundle(3); + bundle.putString("controlPortPath", mIpcDirectory + CONTROL_PORT_FILE); + bundle.putString("socksPath", mIpcDirectory + SOCKS_FILE); + bundle.putString("cookieFilePath", mIpcDirectory + COOKIE_AUTH_FILE); + callback.sendSuccess(bundle); + } + + private synchronized void stopDaemon(final GeckoBundle message, final EventCallback callback) { + if (mTorProcess == null) { + if (callback != null) { + callback.sendSuccess(null); + } + return; + } + String handle = message.getString("handle", ""); + if (!mTorProcess.getHandle().equals(handle)) { + GeckoBundle bundle = new GeckoBundle(1); + bundle.putString( + "error", "The requested process has not been found. It might have already been stopped."); + callback.sendError(bundle); + return; + } + mTorProcess.shutdown(); + mTorProcess = null; + callback.sendSuccess(null); + } + + class TorProcess extends Thread { + private static final String EVENT_TOR_STARTED = "GeckoView:Tor:TorStarted"; + private static final String EVENT_TOR_START_FAILED = "GeckoView:Tor:TorStartFailed"; + private static final String EVENT_TOR_EXITED = "GeckoView:Tor:TorExited"; + private final String mHandle; + private Process mProcess = null; + + TorProcess(String handle) { + mHandle = handle; + setName("tor-process-" + handle); + start(); + } - @Override - protected void onPostExecute(TorSettings torSettings) { - mSettings = torSettings; - if (TorLegacyAndroidSettings.unmigrated()) { - setSettings(mSettings, true, true); - TorLegacyAndroidSettings.setMigrated(); - } + @Override + public void run() { + cleanIpcDirectory(); + + final String ipcDir = TorIntegrationAndroid.this.mIpcDirectory; + final ArrayList<String> args = new ArrayList<>(); + args.add(mLibraryDir + "/libTor.so"); + args.add("DisableNetwork"); + args.add("1"); + args.add("+__ControlPort"); + args.add("unix:" + ipcDir + CONTROL_PORT_FILE); + args.add("+__SocksPort"); + args.add("unix:" + ipcDir + SOCKS_FILE + " IPv6Traffic PreferIPv6 KeepAliveIsolateSOCKSAuth"); + args.add("CookieAuthentication"); + args.add("1"); + args.add("CookieAuthFile"); + args.add(ipcDir + COOKIE_AUTH_FILE); + args.add("DataDirectory"); + args.add(mDataDir.getAbsolutePath()); + boolean copied = true; + try { + copyAndUseConfigFile("--defaults-torrc", "torrc-defaults", args); + } catch (IOException e) { + Log.w( + TAG, "torrc-default cannot be created, pluggable transports will not be available", e); + copied = false; + } + // tor-browser#42607: For now we do not ship geoip databases, as we + // do not have the circuit display functionality and they allow us + // to save some space in the final APK. + /*try { + copyAndUseConfigFile("GeoIPFile", "geoip", args); + copyAndUseConfigFile("GeoIPv6File", "geoip6", args); + } catch (IOException e) { + Log.w(TAG, "GeoIP files cannot be created, this feature will not be available.", e); + copied = false; + }*/ + mCopiedConfigFiles = copied; + + Log.d(TAG, "Starting tor with the follwing args: " + args.toString()); + final ProcessBuilder builder = new ProcessBuilder(args); + builder.directory(new File(mLibraryDir)); + try { + mProcess = builder.start(); + } catch (IOException e) { + Log.e(TAG, "Cannot start tor " + mHandle, e); + final GeckoBundle data = new GeckoBundle(2); + data.putString("handle", mHandle); + data.putString("error", e.getMessage()); + EventDispatcher.getInstance().dispatch(EVENT_TOR_START_FAILED, data); + return; + } + Log.i(TAG, "Tor process " + mHandle + " started."); + { + final GeckoBundle data = new GeckoBundle(1); + data.putString("handle", mHandle); + EventDispatcher.getInstance().dispatch(EVENT_TOR_STARTED, data); + } + try { + BufferedReader reader = + new BufferedReader(new InputStreamReader(mProcess.getInputStream())); + String line; + while ((line = reader.readLine()) != null) { + Log.i(TAG, "[tor-" + mHandle + "] " + line); } + } catch (IOException e) { + Log.e(TAG, "Failed to read stdout of the tor process " + mHandle, e); + } + Log.d(TAG, "Exiting the stdout loop for process " + mHandle); + final GeckoBundle data = new GeckoBundle(2); + data.putString("handle", mHandle); + try { + data.putInt("status", mProcess.waitFor()); + } catch (InterruptedException e) { + Log.e(TAG, "Failed to wait for the tor process " + mHandle, e); + data.putInt("status", 0xdeadbeef); + } + // FIXME: We usually don't reach this when the application is killed! + // So, we don't do our cleanup. + Log.i(TAG, "Tor process " + mHandle + " has exited."); + EventDispatcher.getInstance().dispatch(EVENT_TOR_EXITED, data); } - private synchronized void startDaemon(final GeckoBundle message, final EventCallback callback) { - // Let JS generate this to possibly reduce the chance of race conditions. - String handle = message.getString("handle", ""); - if (handle.isEmpty()) { - Log.e(TAG, "Requested to start a tor process without a handle."); - callback.sendError("Expected a handle for the new process."); - return; + private void cleanIpcDirectory() { + File directory = new File(TorIntegrationAndroid.this.mIpcDirectory); + if (!directory.isDirectory()) { + if (!directory.mkdirs()) { + Log.e(TAG, "Failed to create the IPC directory."); + return; } - Log.d(TAG, "Starting the a tor process with handle " + handle); - - TorProcess previousProcess = mTorProcess; - if (previousProcess != null) { - Log.w(TAG, "We still have a running process: " + previousProcess.getHandle()); + try { + // First remove the permissions for everybody... + directory.setReadable(false, false); + directory.setWritable(false, false); + directory.setExecutable(false, false); + // ... then add them back, but only for the owner. + directory.setReadable(true, true); + directory.setWritable(true, true); + directory.setExecutable(true, true); + } catch (SecurityException e) { + Log.e(TAG, "Could not set the permissions to the IPC directory.", e); } - mTorProcess = new TorProcess(handle); + return; + } + // We assume we do not have child directories, only files + File[] maybeFiles = directory.listFiles(); + if (maybeFiles != null) { + for (File file : maybeFiles) { + if (!file.delete()) { + Log.d(TAG, "Could not delete " + file); + } + } + } + } - GeckoBundle bundle = new GeckoBundle(3); - bundle.putString("controlPortPath", mIpcDirectory + CONTROL_PORT_FILE); - bundle.putString("socksPath", mIpcDirectory + SOCKS_FILE); - bundle.putString("cookieFilePath", mIpcDirectory + COOKIE_AUTH_FILE); - callback.sendSuccess(bundle); + private void copyAndUseConfigFile(String option, String name, ArrayList<String> args) + throws IOException { + File file = copyConfigFile(name); + args.add(option); + args.add(file.getAbsolutePath()); } - private synchronized void stopDaemon(final GeckoBundle message, final EventCallback callback) { - if (mTorProcess == null) { - if (callback != null) { - callback.sendSuccess(null); - } - return; + private File copyConfigFile(String name) throws IOException { + final File file = new File(mCacheDir, name); + if (mCopiedConfigFiles && file.exists()) { + return file; + } + + final Context context = GeckoAppShell.getApplicationContext(); + final InputStream in = context.getAssets().open("common/" + name); + // Files.copy is API 26+, so use java.io and a loop for now. + FileOutputStream out = null; + try { + out = new FileOutputStream(file); + } catch (IOException e) { + in.close(); + throw e; + } + try { + byte buffer[] = new byte[4096]; + int read; + while ((read = in.read(buffer)) >= 0) { + out.write(buffer, 0, read); } - String handle = message.getString("handle", ""); - if (!mTorProcess.getHandle().equals(handle)) { - GeckoBundle bundle = new GeckoBundle(1); - bundle.putString("error", "The requested process has not been found. It might have already been stopped."); - callback.sendError(bundle); - return; + } finally { + try { + in.close(); + } catch (IOException e) { + Log.w(TAG, "Cannot close the input stream for " + name); } - mTorProcess.shutdown(); - mTorProcess = null; - callback.sendSuccess(null); + try { + out.close(); + } catch (IOException e) { + Log.w(TAG, "Cannot close the output stream for " + name); + } + } + return file; } - class TorProcess extends Thread { - private static final String EVENT_TOR_STARTED = "GeckoView:Tor:TorStarted"; - private static final String EVENT_TOR_START_FAILED = "GeckoView:Tor:TorStartFailed"; - private static final String EVENT_TOR_EXITED = "GeckoView:Tor:TorExited"; - private final String mHandle; - private Process mProcess = null; - - TorProcess(String handle) { - mHandle = handle; - setName("tor-process-" + handle); - start(); + public void shutdown() { + if (mProcess != null && mProcess.isAlive()) { + mProcess.destroy(); + } + if (isAlive()) { + try { + join(); + } catch (InterruptedException e) { + Log.e( + TAG, + "Cannot join the thread for tor process " + mHandle + ", possibly already terminated", + e); } + } + } - @Override - public void run() { - cleanIpcDirectory(); - - final String ipcDir = TorIntegrationAndroid.this.mIpcDirectory; - final ArrayList<String> args = new ArrayList<>(); - args.add(mLibraryDir + "/libTor.so"); - args.add("DisableNetwork"); - args.add("1"); - args.add("+__ControlPort"); - args.add("unix:" + ipcDir + CONTROL_PORT_FILE); - args.add("+__SocksPort"); - args.add("unix:" + ipcDir + SOCKS_FILE + " IPv6Traffic PreferIPv6 KeepAliveIsolateSOCKSAuth"); - args.add("CookieAuthentication"); - args.add("1"); - args.add("CookieAuthFile"); - args.add(ipcDir + COOKIE_AUTH_FILE); - args.add("DataDirectory"); - args.add(mDataDir.getAbsolutePath()); - boolean copied = true; - try { - copyAndUseConfigFile("--defaults-torrc", "torrc-defaults", args); - } catch (IOException e) { - Log.w(TAG, "torrc-default cannot be created, pluggable transports will not be available", e); - copied = false; - } - // tor-browser#42607: For now we do not ship geoip databases, as we - // do not have the circuit display functionality and they allow us - // to save some space in the final APK. - /*try { - copyAndUseConfigFile("GeoIPFile", "geoip", args); - copyAndUseConfigFile("GeoIPv6File", "geoip6", args); - } catch (IOException e) { - Log.w(TAG, "GeoIP files cannot be created, this feature will not be available.", e); - copied = false; - }*/ - mCopiedConfigFiles = copied; - - Log.d(TAG, "Starting tor with the follwing args: " + args.toString()); - final ProcessBuilder builder = new ProcessBuilder(args); - builder.directory(new File(mLibraryDir)); - try { - mProcess = builder.start(); - } catch (IOException e) { - Log.e(TAG, "Cannot start tor " + mHandle, e); - final GeckoBundle data = new GeckoBundle(2); - data.putString("handle", mHandle); - data.putString("error", e.getMessage()); - EventDispatcher.getInstance().dispatch(EVENT_TOR_START_FAILED, data); - return; - } - Log.i(TAG, "Tor process " + mHandle + " started."); - { - final GeckoBundle data = new GeckoBundle(1); - data.putString("handle", mHandle); - EventDispatcher.getInstance().dispatch(EVENT_TOR_STARTED, data); - } - try { - BufferedReader reader = new BufferedReader(new InputStreamReader(mProcess.getInputStream())); - String line; - while ((line = reader.readLine()) != null) { - Log.i(TAG, "[tor-" + mHandle + "] " + line); - } - } catch (IOException e) { - Log.e(TAG, "Failed to read stdout of the tor process " + mHandle, e); - } - Log.d(TAG, "Exiting the stdout loop for process " + mHandle); - final GeckoBundle data = new GeckoBundle(2); - data.putString("handle", mHandle); - try { - data.putInt("status", mProcess.waitFor()); - } catch (InterruptedException e) { - Log.e(TAG, "Failed to wait for the tor process " + mHandle, e); - data.putInt("status", 0xdeadbeef); - } - // FIXME: We usually don't reach this when the application is killed! - // So, we don't do our cleanup. - Log.i(TAG, "Tor process " + mHandle + " has exited."); - EventDispatcher.getInstance().dispatch(EVENT_TOR_EXITED, data); - } + public String getHandle() { + return mHandle; + } + } + + private synchronized void startMeek(final GeckoBundle message, final EventCallback callback) { + if (callback == null) { + Log.e(TAG, "Tried to start Meek without a callback."); + return; + } + mMeekCounter++; + mMeeks.put( + new Integer(mMeekCounter), + new MeekTransport(callback, mMeekCounter, message.getStringArray("arguments"))); + } + + private synchronized void stopMeek(final GeckoBundle message, final EventCallback callback) { + final Integer key = message.getInteger("id"); + final MeekTransport meek = mMeeks.remove(key); + if (meek != null) { + meek.shutdown(); + } + if (callback != null) { + callback.sendSuccess(null); + } + } + + private class MeekTransport extends Thread { + private static final String TRANSPORT = "meek_lite"; + private Process mProcess; + private final EventCallback mCallback; + private final int mId; + + MeekTransport(final EventCallback callback, int id, String[] args) { + setName("meek-" + id); + + final String command = mLibraryDir + "/libObfs4proxy.so"; + ArrayList<String> argList = new ArrayList<String>(); + argList.add(command); + if (args != null && args.length > 0) { + // Normally not used, but it helps to debug only by editing JS. + Log.d(TAG, "Requested custom arguments for meek: " + String.join(" ", args)); + argList.addAll(Arrays.asList(args)); + } + final ProcessBuilder builder = new ProcessBuilder(argList); + + File ptStateDir = new File(mDataDir, "pt_state"); + Log.d(TAG, "Using " + ptStateDir.getAbsolutePath() + " as a state directory for meek."); + final Map<String, String> env = builder.environment(); + env.put("TOR_PT_MANAGED_TRANSPORT_VER", "1"); + env.put("TOR_PT_STATE_LOCATION", ptStateDir.getAbsolutePath()); + env.put("TOR_PT_EXIT_ON_STDIN_CLOSE", "1"); + env.put("TOR_PT_CLIENT_TRANSPORTS", TRANSPORT); + + mCallback = callback; + mId = id; + try { + // We expect this process to be short-lived, therefore we do not bother with + // implementing this as a service. + mProcess = builder.start(); + } catch (IOException e) { + Log.e(TAG, "Cannot start the PT", e); + callback.sendError(e.getMessage()); + return; + } + start(); + } - private void cleanIpcDirectory() { - File directory = new File(TorIntegrationAndroid.this.mIpcDirectory); - if (!directory.isDirectory()) { - if (!directory.mkdirs()) { - Log.e(TAG, "Failed to create the IPC directory."); - return; - } - try { - // First remove the permissions for everybody... - directory.setReadable(false, false); - directory.setWritable(false, false); - directory.setExecutable(false, false); - // ... then add them back, but only for the owner. - directory.setReadable(true, true); - directory.setWritable(true, true); - directory.setExecutable(true, true); - } catch (SecurityException e) { - Log.e(TAG, "Could not set the permissions to the IPC directory.", e); - } - return; + /** + * Parse the standard output of the pluggable transport to find the hostname and port it is + * listening on. + * + * <p>See also the specs for the IPC protocol at https://spec.torproject.org/pt-spec/ipc.html. + */ + @Override + public void run() { + final String PROTOCOL_VERSION = "1"; + String hostname = ""; + boolean valid = false; + int port = 0; + String error = "Did not see a CMETHOD"; + try { + InputStreamReader isr = new InputStreamReader(mProcess.getInputStream()); + BufferedReader reader = new BufferedReader(isr); + String line; + while ((line = reader.readLine()) != null) { + line = line.trim(); + Log.d(TAG, "Meek line: " + line); + // Split produces always at least one item + String[] tokens = line.split(" "); + if ("VERSION".equals(tokens[0]) + && (tokens.length != 2 || !PROTOCOL_VERSION.equals(tokens[1]))) { + error = "Bad version: " + line; + break; + } + if ("CMETHOD".equals(tokens[0])) { + if (tokens.length != 4) { + error = "Bad number of tokens in CMETHOD: " + line; + break; } - // We assume we do not have child directories, only files - File[] maybeFiles = directory.listFiles(); - if (maybeFiles != null) { - for (File file : maybeFiles) { - if (!file.delete()) { - Log.d(TAG, "Could not delete " + file); - } - } + if (!tokens[1].equals(TRANSPORT)) { + error = "Unexpected transport: " + tokens[1]; + break; } - } - - private void copyAndUseConfigFile(String option, String name, ArrayList<String> args) throws IOException { - File file = copyConfigFile(name); - args.add(option); - args.add(file.getAbsolutePath()); - } - - private File copyConfigFile(String name) throws IOException { - final File file = new File(mCacheDir, name); - if (mCopiedConfigFiles && file.exists()) { - return file; + if (!"socks5".equals(tokens[2])) { + error = "Unexpected proxy type: " + tokens[2]; + break; } - - final Context context = GeckoAppShell.getApplicationContext(); - final InputStream in = context.getAssets().open("common/" + name); - // Files.copy is API 26+, so use java.io and a loop for now. - FileOutputStream out = null; - try { - out = new FileOutputStream(file); - } catch (IOException e) { - in.close(); - throw e; + String[] addr = tokens[3].split(":"); + if (addr.length != 2) { + error = "Invalid address"; + break; } + hostname = addr[0]; try { - byte buffer[] = new byte[4096]; - int read; - while ((read = in.read(buffer)) >= 0) { - out.write(buffer, 0, read); - } - } finally { - try { - in.close(); - } catch (IOException e) { - Log.w(TAG, "Cannot close the input stream for " + name); - } - try { - out.close(); - } catch (IOException e) { - Log.w(TAG, "Cannot close the output stream for " + name); - } - } - return file; - } - - public void shutdown() { - if (mProcess != null && mProcess.isAlive()) { - mProcess.destroy(); + port = Integer.parseInt(addr[1]); + } catch (NumberFormatException e) { + error = "Invalid port: " + e.getMessage(); + break; } - if (isAlive()) { - try { - join(); - } catch (InterruptedException e) { - Log.e(TAG, "Cannot join the thread for tor process " + mHandle + ", possibly already terminated", e); - } + if (port < 1 || port > 65535) { + error = "Invalid port: out of bounds"; + break; } + valid = true; + break; + } + if (tokens[0].endsWith("-ERROR")) { + error = "Seen an error: " + line; + break; + } } - - public String getHandle() { - return mHandle; - } + } catch (Exception e) { + error = e.getMessage(); + } + if (valid) { + Log.d(TAG, "Setup a meek transport " + mId + ": " + hostname + ":" + port); + final GeckoBundle bundle = new GeckoBundle(3); + bundle.putInt("id", mId); + bundle.putString("address", hostname); + bundle.putInt("port", port); + mCallback.sendSuccess(bundle); + } else { + Log.e(TAG, "Failed to get a usable config from the PT: " + error); + mCallback.sendError(error); + return; + } + dumpStdout(); } - private synchronized void startMeek(final GeckoBundle message, final EventCallback callback) { - if (callback == null) { - Log.e(TAG, "Tried to start Meek without a callback."); - return; - } - mMeekCounter++; - mMeeks.put(new Integer(mMeekCounter), new MeekTransport(callback, mMeekCounter)); + void shutdown() { + if (mProcess != null) { + Log.i(TAG, "Shutting down meek process " + mId); + mProcess.destroy(); + mProcess = null; + } else { + Log.w( + TAG, + "Shutdown request on the meek process " + mId + " that has already been shutdown."); + } + try { + join(); + } catch (InterruptedException e) { + Log.e(TAG, "Could not join the meek thread", e); + } } - private synchronized void stopMeek(final GeckoBundle message, final EventCallback callback) { - final Integer key = message.getInteger("id"); - final MeekTransport meek = mMeeks.remove(key); - if (meek != null) { - meek.shutdown(); - } - if (callback != null) { - callback.sendSuccess(null); + void dumpStdout() { + try { + BufferedReader reader = + new BufferedReader(new InputStreamReader(mProcess.getInputStream())); + String line; + while ((line = reader.readLine()) != null) { + Log.d(TAG, "[meek-" + mId + "] " + line); } + } catch (InterruptedIOException e) { + // This happens normally, do not log it. + } catch (IOException e) { + Log.e(TAG, "Failed to read stdout of the meek process process " + mId, e); + } } + } - private class MeekTransport extends Thread { - private static final String TRANSPORT = "meek_lite"; - private Process mProcess; - private final EventCallback mCallback; - private final int mId; - - MeekTransport(final EventCallback callback, int id) { - setName("meek-" + id); - final ProcessBuilder builder = new ProcessBuilder(mLibraryDir + "/libObfs4proxy.so"); - { - File ptStateDir = new File(mDataDir, "pt_state"); - final Map<String, String> env = builder.environment(); - env.put("TOR_PT_MANAGED_TRANSPORT_VER", "1"); - env.put("TOR_PT_STATE_LOCATION", ptStateDir.getAbsolutePath()); - env.put("TOR_PT_EXIT_ON_STDIN_CLOSE", "1"); - env.put("TOR_PT_CLIENT_TRANSPORTS", TRANSPORT); - } - mCallback = callback; - mId = id; - try { - // We expect this process to be short-lived, therefore we do not bother with - // implementing this as a service. - mProcess = builder.start(); - } catch (IOException e) { - Log.e(TAG, "Cannot start the PT", e); - callback.sendError(e.getMessage()); - return; - } - start(); - } + public interface BootstrapStateChangeListener { + void onBootstrapStateChange(String state); - /** - * Parse the standard output of the pluggable transport to find the hostname and port it is - * listening on. - * <p> - * See also the specs for the IPC protocol at https://spec.torproject.org/pt-spec/ipc.html. - */ - @Override - public void run() { - final String PROTOCOL_VERSION = "1"; - String hostname = ""; - boolean valid = false; - int port = 0; - String error = "Did not see a CMETHOD"; - try { - InputStreamReader isr = new InputStreamReader(mProcess.getInputStream()); - BufferedReader reader = new BufferedReader(isr); - String line; - while ((line = reader.readLine()) != null) { - line = line.trim(); - Log.d(TAG, "Meek line: " + line); - // Split produces always at least one item - String[] tokens = line.split(" "); - if ("VERSION".equals(tokens[0]) && (tokens.length != 2 || !PROTOCOL_VERSION.equals(tokens[1]))) { - error = "Bad version: " + line; - break; - } - if ("CMETHOD".equals(tokens[0])) { - if (tokens.length != 4) { - error = "Bad number of tokens in CMETHOD: " + line; - break; - } - if (!tokens[1].equals(TRANSPORT)) { - error = "Unexpected transport: " + tokens[1]; - break; - } - if (!"socks5".equals(tokens[2])) { - error = "Unexpected proxy type: " + tokens[2]; - break; - } - String[] addr = tokens[3].split(":"); - if (addr.length != 2) { - error = "Invalid address"; - break; - } - hostname = addr[0]; - try { - port = Integer.parseInt(addr[1]); - } catch (NumberFormatException e) { - error = "Invalid port: " + e.getMessage(); - break; - } - if (port < 1 || port > 65535) { - error = "Invalid port: out of bounds"; - break; - } - valid = true; - break; - } - if (tokens[0].endsWith("-ERROR")) { - error = "Seen an error: " + line; - break; - } - } - } catch (Exception e) { - error = e.getMessage(); - } - if (valid) { - Log.d(TAG, "Setup a meek transport " + mId + ": " + hostname + ":" + port); - final GeckoBundle bundle = new GeckoBundle(3); - bundle.putInt("id", mId); - bundle.putString("address", hostname); - bundle.putInt("port", port); - mCallback.sendSuccess(bundle); - } else { - Log.e(TAG, "Failed to get a usable config from the PT: " + error); - mCallback.sendError(error); - } - } + void onBootstrapProgress(double progress, boolean hasWarnings); - void shutdown() { - if (mProcess != null) { - mProcess.destroy(); - mProcess = null; - } - try { - join(); - } catch (InterruptedException e) { - Log.e(TAG, "Could not join the meek thread", e); - } - } - } + void onBootstrapComplete(); - public interface BootstrapStateChangeListener { - void onBootstrapStateChange(String state); - void onBootstrapProgress(double progress, boolean hasWarnings); - void onBootstrapComplete(); - void onBootstrapError(String code, String message, String phase, String reason); - void onSettingsRequested(); - } + void onBootstrapError(String code, String message, String phase, String reason); - public interface TorLogListener { - void onLog(String logType, String message); - } + void onSettingsRequested(); + } - private @NonNull void reloadSettings() { - EventDispatcher.getInstance().queryBundle(EVENT_SETTINGS_GET).then( new GeckoResult.OnValueListener<GeckoBundle, Void>() { - public GeckoResult<Void> onValue(final GeckoBundle bundle) { + public interface TorLogListener { + void onLog(String logType, String message); + } + + private @NonNull void reloadSettings() { + EventDispatcher.getInstance() + .queryBundle(EVENT_SETTINGS_GET) + .then( + new GeckoResult.OnValueListener<GeckoBundle, Void>() { + public GeckoResult<Void> onValue(final GeckoBundle bundle) { mSettings = new TorSettings(bundle); return new GeckoResult<Void>(); - } - }); - } + } + }); + } - public TorSettings getSettings() { - return mSettings; - } + public TorSettings getSettings() { + return mSettings; + } - public void setSettings(final TorSettings settings, boolean save, boolean apply) { - mSettings = settings; + public void setSettings(final TorSettings settings, boolean save, boolean apply) { + mSettings = settings; - emitSetSettings(settings, save, apply).then( + emitSetSettings(settings, save, apply) + .then( new GeckoResult.OnValueListener<Void, Void>() { - public GeckoResult<Void> onValue(Void v) { - return new GeckoResult<Void>(); - } + public GeckoResult<Void> onValue(Void v) { + return new GeckoResult<Void>(); + } }, new GeckoResult.OnExceptionListener<Void>() { - public GeckoResult<Void> onException(final Throwable e) { - Log.e(TAG, "Failed to set settings", e); - reloadSettings(); - return new GeckoResult<Void>(); - } + public GeckoResult<Void> onException(final Throwable e) { + Log.e(TAG, "Failed to set settings", e); + reloadSettings(); + return new GeckoResult<Void>(); + } }); - } - - private @NonNull GeckoResult<Void> emitSetSettings(final TorSettings settings, boolean save, boolean apply) { - GeckoBundle bundle = new GeckoBundle(3); - bundle.putBoolean("save", save); - bundle.putBoolean("apply", apply); - bundle.putBundle("settings", settings.asGeckoBundle()); - return EventDispatcher.getInstance().queryVoid(EVENT_SETTINGS_SET, bundle); - } - - public @NonNull GeckoResult<Void> applySettings() { - return EventDispatcher.getInstance().queryVoid(EVENT_SETTINGS_APPLY); - } - - public @NonNull GeckoResult<Void> saveSettings() { - return EventDispatcher.getInstance().queryVoid(EVENT_SETTINGS_SAVE); - } - - public @NonNull GeckoResult<Void> beginBootstrap() { - return EventDispatcher.getInstance().queryVoid(EVENT_BOOTSTRAP_BEGIN); - } - - public @NonNull GeckoResult<Void> beginAutoBootstrap(final String countryCode) { - final GeckoBundle bundle = new GeckoBundle(1); - bundle.putString("countryCode", countryCode); - return EventDispatcher.getInstance().queryVoid(EVENT_BOOTSTRAP_BEGIN_AUTO, bundle); - } - - public @NonNull GeckoResult<Void> beginAutoBootstrap() { - return beginAutoBootstrap(null); - } - - public @NonNull GeckoResult<Void> cancelBootstrap() { - return EventDispatcher.getInstance().queryVoid(EVENT_BOOTSTRAP_CANCEL); - } - - public void registerBootstrapStateChangeListener(BootstrapStateChangeListener listener) { - mBootstrapStateListeners.add(listener); - } - - public void unregisterBootstrapStateChangeListener(BootstrapStateChangeListener listener) { - mBootstrapStateListeners.remove(listener); - } - - private final HashSet<BootstrapStateChangeListener> mBootstrapStateListeners = new HashSet<>(); - - public void registerLogListener(TorLogListener listener) { - mLogListeners.add(listener); - } - - public void unregisterLogListener(TorLogListener listener) { - mLogListeners.remove(listener); - } - - private final HashSet<TorLogListener> mLogListeners = new HashSet<>(); + } + + private @NonNull GeckoResult<Void> emitSetSettings( + final TorSettings settings, boolean save, boolean apply) { + GeckoBundle bundle = new GeckoBundle(3); + bundle.putBoolean("save", save); + bundle.putBoolean("apply", apply); + bundle.putBundle("settings", settings.asGeckoBundle()); + return EventDispatcher.getInstance().queryVoid(EVENT_SETTINGS_SET, bundle); + } + + public @NonNull GeckoResult<Void> applySettings() { + return EventDispatcher.getInstance().queryVoid(EVENT_SETTINGS_APPLY); + } + + public @NonNull GeckoResult<Void> saveSettings() { + return EventDispatcher.getInstance().queryVoid(EVENT_SETTINGS_SAVE); + } + + public @NonNull GeckoResult<Void> beginBootstrap() { + return EventDispatcher.getInstance().queryVoid(EVENT_BOOTSTRAP_BEGIN); + } + + public @NonNull GeckoResult<Void> beginAutoBootstrap(final String countryCode) { + final GeckoBundle bundle = new GeckoBundle(1); + bundle.putString("countryCode", countryCode); + return EventDispatcher.getInstance().queryVoid(EVENT_BOOTSTRAP_BEGIN_AUTO, bundle); + } + + public @NonNull GeckoResult<Void> beginAutoBootstrap() { + return beginAutoBootstrap(null); + } + + public @NonNull GeckoResult<Void> cancelBootstrap() { + return EventDispatcher.getInstance().queryVoid(EVENT_BOOTSTRAP_CANCEL); + } + + public void registerBootstrapStateChangeListener(BootstrapStateChangeListener listener) { + mBootstrapStateListeners.add(listener); + } + + public void unregisterBootstrapStateChangeListener(BootstrapStateChangeListener listener) { + mBootstrapStateListeners.remove(listener); + } + + private final HashSet<BootstrapStateChangeListener> mBootstrapStateListeners = new HashSet<>(); + + public void registerLogListener(TorLogListener listener) { + mLogListeners.add(listener); + } + + public void unregisterLogListener(TorLogListener listener) { + mLogListeners.remove(listener); + } + + private final HashSet<TorLogListener> mLogListeners = new HashSet<>(); } ===================================== mobile/android/geckoview/src/main/java/org/mozilla/geckoview/TorSettings.java ===================================== @@ -1,185 +1,192 @@ package org.mozilla.geckoview; import android.util.Log; - import org.mozilla.gecko.util.GeckoBundle; public class TorSettings { - public enum BridgeSource { - Invalid(-1), - BuiltIn(0), - BridgeDB(1), - UserProvided(2); - - private int source; - - BridgeSource(final int source) { - this.source = source; - } - - public static BridgeSource fromInt(int i) { - switch (i) { - case -1: return Invalid; - case 0: return BuiltIn; - case 1: return BridgeDB; - case 2: return UserProvided; - } - return Invalid; - } - - public int toInt() { - return this.source; - } + public enum BridgeSource { + Invalid(-1), + BuiltIn(0), + BridgeDB(1), + UserProvided(2); + + private int source; + + BridgeSource(final int source) { + this.source = source; } - public enum ProxyType { - Invalid(-1), - Socks4(0), - Socks5(1), - HTTPS(2); - - private int type; - - ProxyType(final int type) { - this.type = type; - } - - public int toInt() { - return type; - } - - public static ProxyType fromInt(int i) { - switch (i) { - case -1: return Invalid; - case 0: return Socks4; - case 1: return Socks5; - case 2: return HTTPS; - } - return Invalid; - } + public static BridgeSource fromInt(int i) { + switch (i) { + case -1: + return Invalid; + case 0: + return BuiltIn; + case 1: + return BridgeDB; + case 2: + return UserProvided; + } + return Invalid; } - public enum BridgeBuiltinType { - /* TorSettings.sys.mjs ~ln43: string: obfs4|meek-azure|snowflake|etc */ - Invalid("invalid"), - Obfs4("obfs4"), - MeekAzure("meek-azure"), - Snowflake("snowflake"); + public int toInt() { + return this.source; + } + } + public enum ProxyType { + Invalid(-1), + Socks4(0), + Socks5(1), + HTTPS(2); - private String type; + private int type; - BridgeBuiltinType(String type) { - this.type = type; - } + ProxyType(final int type) { + this.type = type; + } - public String toString() { - return type; - } + public int toInt() { + return type; + } - public static BridgeBuiltinType fromString(String s) { - switch (s) { - case "obfs4": return Obfs4; - case "meek-azure": return MeekAzure; - case "snowflake": return Snowflake; - } - return Invalid; - } + public static ProxyType fromInt(int i) { + switch (i) { + case -1: + return Invalid; + case 0: + return Socks4; + case 1: + return Socks5; + case 2: + return HTTPS; + } + return Invalid; + } + } + + public enum BridgeBuiltinType { + /* TorSettings.sys.mjs ~ln43: string: obfs4|meek-azure|snowflake|etc */ + Invalid("invalid"), + Obfs4("obfs4"), + MeekAzure("meek-azure"), + Snowflake("snowflake"); + + private String type; + BridgeBuiltinType(String type) { + this.type = type; } - private boolean loaded = false; + public String toString() { + return type; + } - public boolean enabled = true; + public static BridgeBuiltinType fromString(String s) { + switch (s) { + case "obfs4": + return Obfs4; + case "meek-azure": + return MeekAzure; + case "snowflake": + return Snowflake; + } + return Invalid; + } + } - public boolean quickstart = false; + private boolean loaded = false; - // bridges section - public boolean bridgesEnabled = false; - public BridgeSource bridgesSource = BridgeSource.Invalid; - public BridgeBuiltinType bridgesBuiltinType = BridgeBuiltinType.Invalid; - public String[] bridgeBridgeStrings; + public boolean enabled = true; - // proxy section - public boolean proxyEnabled = false; - public ProxyType proxyType = ProxyType.Invalid; - public String proxyAddress = ""; - public int proxyPort = 0; - public String proxyUsername = ""; - public String proxyPassword = ""; + public boolean quickstart = false; - // firewall section - public boolean firewallEnabled = false; - public int[] firewallAllowedPorts; + // bridges section + public boolean bridgesEnabled = false; + public BridgeSource bridgesSource = BridgeSource.Invalid; + public BridgeBuiltinType bridgesBuiltinType = BridgeBuiltinType.Invalid; + public String[] bridgeBridgeStrings; - public TorSettings() { - } + // proxy section + public boolean proxyEnabled = false; + public ProxyType proxyType = ProxyType.Invalid; + public String proxyAddress = ""; + public int proxyPort = 0; + public String proxyUsername = ""; + public String proxyPassword = ""; + + // firewall section + public boolean firewallEnabled = false; + public int[] firewallAllowedPorts; + + public TorSettings() {} + + public TorSettings(GeckoBundle bundle) { + try { + GeckoBundle qs = bundle.getBundle("quickstart"); + GeckoBundle bridges = bundle.getBundle("bridges"); + GeckoBundle proxy = bundle.getBundle("proxy"); + GeckoBundle firewall = bundle.getBundle("firewall"); + + bridgesEnabled = bridges.getBoolean("enabled"); + bridgesSource = BridgeSource.fromInt(bridges.getInt("source")); + bridgesBuiltinType = BridgeBuiltinType.fromString(bridges.getString("builtin_type")); + bridgeBridgeStrings = bridges.getStringArray("bridge_strings"); - public TorSettings(GeckoBundle bundle) { - try { - GeckoBundle qs = bundle.getBundle("quickstart"); - GeckoBundle bridges = bundle.getBundle("bridges"); - GeckoBundle proxy = bundle.getBundle("proxy"); - GeckoBundle firewall = bundle.getBundle("firewall"); - - bridgesEnabled = bridges.getBoolean("enabled"); - bridgesSource = BridgeSource.fromInt(bridges.getInt("source")); - bridgesBuiltinType = BridgeBuiltinType.fromString(bridges.getString("builtin_type")); - bridgeBridgeStrings = bridges.getStringArray("bridge_strings"); - - quickstart = qs.getBoolean("enabled"); - - firewallEnabled = firewall.getBoolean("enabled"); - firewallAllowedPorts = firewall.getIntArray("allowed_ports"); - - proxyEnabled = proxy.getBoolean("enabled"); - proxyAddress = proxy.getString("address"); - proxyUsername = proxy.getString("username"); - proxyPassword = proxy.getString("password"); - proxyPort = proxy.getInt("port"); - proxyType = ProxyType.fromInt(proxy.getInt("type")); - - loaded = true; - } catch (Exception e) { - Log.e("TorSettings", "bundle access error: " + e.toString(), e); - } + quickstart = qs.getBoolean("enabled"); + + firewallEnabled = firewall.getBoolean("enabled"); + firewallAllowedPorts = firewall.getIntArray("allowed_ports"); + + proxyEnabled = proxy.getBoolean("enabled"); + proxyAddress = proxy.getString("address"); + proxyUsername = proxy.getString("username"); + proxyPassword = proxy.getString("password"); + proxyPort = proxy.getInt("port"); + proxyType = ProxyType.fromInt(proxy.getInt("type")); + + loaded = true; + } catch (Exception e) { + Log.e("TorSettings", "bundle access error: " + e.toString(), e); } + } - public GeckoBundle asGeckoBundle() { - GeckoBundle bundle = new GeckoBundle(); + public GeckoBundle asGeckoBundle() { + GeckoBundle bundle = new GeckoBundle(); - GeckoBundle qs = new GeckoBundle(); - GeckoBundle bridges = new GeckoBundle(); - GeckoBundle proxy = new GeckoBundle(); - GeckoBundle firewall = new GeckoBundle(); + GeckoBundle qs = new GeckoBundle(); + GeckoBundle bridges = new GeckoBundle(); + GeckoBundle proxy = new GeckoBundle(); + GeckoBundle firewall = new GeckoBundle(); - bridges.putBoolean("enabled", bridgesEnabled); - bridges.putInt("source", bridgesSource.toInt()); - bridges.putString("builtin_type", bridgesBuiltinType.toString()); - bridges.putStringArray("bridge_strings", bridgeBridgeStrings); + bridges.putBoolean("enabled", bridgesEnabled); + bridges.putInt("source", bridgesSource.toInt()); + bridges.putString("builtin_type", bridgesBuiltinType.toString()); + bridges.putStringArray("bridge_strings", bridgeBridgeStrings); - qs.putBoolean("enabled", quickstart); + qs.putBoolean("enabled", quickstart); - firewall.putBoolean("enabled", firewallEnabled); - firewall.putIntArray("allowed_ports", firewallAllowedPorts); + firewall.putBoolean("enabled", firewallEnabled); + firewall.putIntArray("allowed_ports", firewallAllowedPorts); - proxy.putBoolean("enabled", proxyEnabled); - proxy.putString("address", proxyAddress); - proxy.putString("username", proxyUsername); - proxy.putString("password", proxyPassword); - proxy.putInt("port", proxyPort); - proxy.putInt("type", proxyType.toInt()); + proxy.putBoolean("enabled", proxyEnabled); + proxy.putString("address", proxyAddress); + proxy.putString("username", proxyUsername); + proxy.putString("password", proxyPassword); + proxy.putInt("port", proxyPort); + proxy.putInt("type", proxyType.toInt()); - bundle.putBundle("quickstart", qs); - bundle.putBundle("bridges", bridges); - bundle.putBundle("proxy", proxy); - bundle.putBundle("firewall", firewall); + bundle.putBundle("quickstart", qs); + bundle.putBundle("bridges", bridges); + bundle.putBundle("proxy", proxy); + bundle.putBundle("firewall", firewall); - return bundle; - } + return bundle; + } - public boolean isLoaded() { - return this.loaded; - } + public boolean isLoaded() { + return this.loaded; + } } ===================================== mobile/android/geckoview/src/main/java/org/mozilla/geckoview/WebRequest.java ===================================== @@ -49,9 +49,7 @@ public class WebRequest extends WebMessage { /** The value of the Referer header for this request. */ public final @Nullable String referrer; - /** - * The value of the origin of this request. - */ + /** The value of the origin of this request. */ public final @Nullable String origin; @Retention(RetentionPolicy.SOURCE) @@ -248,10 +246,10 @@ public class WebRequest extends WebMessage { * @param origin A URI String * @return This Builder instance. */ - public @NonNull Builder origin(final @Nullable String origin) { - mOrigin = origin; - return this; - } + public @NonNull Builder origin(final @Nullable String origin) { + mOrigin = origin; + return this; + } /** * @return A {@link WebRequest} constructed with the values from this Builder instance. ===================================== mobile/android/geckoview/src/main/java/org/mozilla/geckoview/androidlegacysettings/Prefs.java ===================================== @@ -2,71 +2,68 @@ package org.mozilla.geckoview.androidlegacysettings; import android.content.Context; import android.content.SharedPreferences; -import org.mozilla.gecko.GeckoAppShell; - import java.util.Locale; +import org.mozilla.gecko.GeckoAppShell; // tor-android-service utils/Prefs.java /* package */ class Prefs { - private final static String PREF_BRIDGES_ENABLED = "pref_bridges_enabled"; - private final static String PREF_BRIDGES_LIST = "pref_bridges_list"; + private static final String PREF_BRIDGES_ENABLED = "pref_bridges_enabled"; + private static final String PREF_BRIDGES_LIST = "pref_bridges_list"; - private static SharedPreferences prefs; + private static SharedPreferences prefs; - // OrbotConstants - private final static String PREF_TOR_SHARED_PREFS = "org.torproject.android_preferences"; + // OrbotConstants + private static final String PREF_TOR_SHARED_PREFS = "org.torproject.android_preferences"; + // tor-android-service utils/TorServiceUtil.java - // tor-android-service utils/TorServiceUtil.java - - private static void setContext() { - if (prefs == null) { - prefs = GeckoAppShell.getApplicationContext().getSharedPreferences(PREF_TOR_SHARED_PREFS, - Context.MODE_MULTI_PROCESS); - } + private static void setContext() { + if (prefs == null) { + prefs = + GeckoAppShell.getApplicationContext() + .getSharedPreferences(PREF_TOR_SHARED_PREFS, Context.MODE_MULTI_PROCESS); } - - public static boolean getBoolean(String key, boolean def) { - setContext(); - return prefs.getBoolean(key, def); - } - - public static void putBoolean(String key, boolean value) { - setContext(); - prefs.edit().putBoolean(key, value).apply(); - } - - public static void putString(String key, String value) { - setContext(); - prefs.edit().putString(key, value).apply(); + } + + public static boolean getBoolean(String key, boolean def) { + setContext(); + return prefs.getBoolean(key, def); + } + + public static void putBoolean(String key, boolean value) { + setContext(); + prefs.edit().putBoolean(key, value).apply(); + } + + public static void putString(String key, String value) { + setContext(); + prefs.edit().putString(key, value).apply(); + } + + public static String getString(String key, String def) { + setContext(); + return prefs.getString(key, def); + } + + public static boolean bridgesEnabled() { + setContext(); + // for Locale.getDefault().getLanguage().equals("fa"), bridges were enabled by default (and + // it was meek). This was a default set in 2019 code, but it is not a good default anymore, + // so we removed the check. + return prefs.getBoolean(PREF_BRIDGES_ENABLED, false); + } + + public static String getBridgesList() { + setContext(); + String list = prefs.getString(PREF_BRIDGES_LIST, ""); + // list might be empty if the default PT was used, so check also if bridges are enabled. + if (list.isEmpty() && prefs.getBoolean(PREF_BRIDGES_ENABLED, false)) { + // Even though the check on the fa locale is not good to enable bridges by default, we + // still check it here, because if the list was empty, it was likely that it was the + // choice for users with this locale. + return (Locale.getDefault().getLanguage().equals("fa")) ? "meek" : "obfs4"; } - - public static String getString(String key, String def) { - setContext(); - return prefs.getString(key, def); - } - - public static boolean bridgesEnabled() { - setContext(); - // for Locale.getDefault().getLanguage().equals("fa"), bridges were enabled by default (and - // it was meek). This was a default set in 2019 code, but it is not a good default anymore, - // so we removed the check. - return prefs.getBoolean(PREF_BRIDGES_ENABLED, false); - } - - public static String getBridgesList() { - setContext(); - String list = prefs.getString(PREF_BRIDGES_LIST, ""); - // list might be empty if the default PT was used, so check also if bridges are enabled. - if (list.isEmpty() && prefs.getBoolean(PREF_BRIDGES_ENABLED, false)) { - // Even though the check on the fa locale is not good to enable bridges by default, we - // still check it here, because if the list was empty, it was likely that it was the - // choice for users with this locale. - return (Locale.getDefault().getLanguage().equals("fa")) ? "meek": "obfs4"; - } - return list; - } - - + return list; + } } ===================================== mobile/android/geckoview/src/main/java/org/mozilla/geckoview/androidlegacysettings/TorLegacyAndroidSettings.java ===================================== @@ -4,70 +4,71 @@ import org.mozilla.geckoview.TorSettings; public class TorLegacyAndroidSettings { - private static String PREF_USE_MOZ_PREFS = "tor_use_moz_prefs"; + private static String PREF_USE_MOZ_PREFS = "tor_use_moz_prefs"; - public static boolean unmigrated() { - return !Prefs.getBoolean(PREF_USE_MOZ_PREFS, false); - } + public static boolean unmigrated() { + return !Prefs.getBoolean(PREF_USE_MOZ_PREFS, false); + } - public static void setUnmigrated() { - Prefs.putBoolean(PREF_USE_MOZ_PREFS, false); - } + public static void setUnmigrated() { + Prefs.putBoolean(PREF_USE_MOZ_PREFS, false); + } - public static void setMigrated() { - Prefs.putBoolean(PREF_USE_MOZ_PREFS, true); - } + public static void setMigrated() { + Prefs.putBoolean(PREF_USE_MOZ_PREFS, true); + } - public static TorSettings loadTorSettings() { - TorSettings settings = new TorSettings(); + public static TorSettings loadTorSettings() { + TorSettings settings = new TorSettings(); - // always true, tor is enabled in TB - settings.enabled = true; + // always true, tor is enabled in TB + settings.enabled = true; - // firefox-android disconnected quick start a while ago so it's untracked - settings.quickstart = false; + // firefox-android disconnected quick start a while ago so it's untracked + settings.quickstart = false; - settings.bridgesEnabled = Prefs.bridgesEnabled(); + settings.bridgesEnabled = Prefs.bridgesEnabled(); - // tor-android-service CustomTorInstaller.java -/* - BridgesList is an overloaded field, which can cause some confusion. - The list can be: - 1) a filter like obfs4, meek, or snowflake OR - 2) it can be a custom bridge - For (1), we just pass back all bridges, the filter will occur - elsewhere in the library. - For (2) we return the bridge list as a raw stream. - If length is greater than 9, then we know this is a custom bridge - */ - String userDefinedBridgeList = Prefs.getBridgesList(); - boolean userDefinedBridge = userDefinedBridgeList.length() > 9; - // Terrible hack. Must keep in sync with topl::addBridgesFromResources. - if (!userDefinedBridge) { - settings.bridgesSource = TorSettings.BridgeSource.BuiltIn; - switch (userDefinedBridgeList) { - case "obfs4": - case "snowflake": - settings.bridgesBuiltinType = TorSettings.BridgeBuiltinType.fromString(userDefinedBridgeList); - break; - case "meek": - settings.bridgesBuiltinType = TorSettings.BridgeBuiltinType.MeekAzure; - break; - default: - settings.bridgesSource = TorSettings.BridgeSource.Invalid; - break; - } - } else { - settings.bridgesSource = TorSettings.BridgeSource.UserProvided; // user provided - settings.bridgeBridgeStrings = userDefinedBridgeList.split("\r\n"); - } + // tor-android-service CustomTorInstaller.java + /* + BridgesList is an overloaded field, which can cause some confusion. + The list can be: + 1) a filter like obfs4, meek, or snowflake OR + 2) it can be a custom bridge + For (1), we just pass back all bridges, the filter will occur + elsewhere in the library. + For (2) we return the bridge list as a raw stream. + If length is greater than 9, then we know this is a custom bridge + */ + String userDefinedBridgeList = Prefs.getBridgesList(); + boolean userDefinedBridge = userDefinedBridgeList.length() > 9; + // Terrible hack. Must keep in sync with topl::addBridgesFromResources. + if (!userDefinedBridge) { + settings.bridgesSource = TorSettings.BridgeSource.BuiltIn; + switch (userDefinedBridgeList) { + case "obfs4": + case "snowflake": + settings.bridgesBuiltinType = + TorSettings.BridgeBuiltinType.fromString(userDefinedBridgeList); + break; + case "meek": + settings.bridgesBuiltinType = TorSettings.BridgeBuiltinType.MeekAzure; + break; + default: + settings.bridgesSource = TorSettings.BridgeSource.Invalid; + break; + } + } else { + settings.bridgesSource = TorSettings.BridgeSource.UserProvided; // user provided + settings.bridgeBridgeStrings = userDefinedBridgeList.split("\r\n"); + } - // Tor Browser Android doesn't take proxy and firewall settings - settings.proxyEnabled = false; + // Tor Browser Android doesn't take proxy and firewall settings + settings.proxyEnabled = false; - settings.firewallEnabled = false; - settings.firewallAllowedPorts = new int[0]; + settings.firewallEnabled = false; + settings.firewallAllowedPorts = new int[0]; - return settings; - } + return settings; + } } ===================================== toolkit/modules/DomainFrontedRequests.sys.mjs ===================================== @@ -444,7 +444,7 @@ export class DomainFrontRequestBuilder { async init(reflector, front) { if (this.#inited) { - throw new Error("MoatRPC: Already initialized"); + throw new Error("DomainFrontRequestBuilder: Already initialized"); } const meekTransport = @@ -464,7 +464,7 @@ export class DomainFrontRequestBuilder { buildHttpHandler(uriString) { if (!this.#inited) { - throw new Error("MoatRPC: Not initialized"); + throw new Error("DomainFrontRequestBuilder: Not initialized"); } const { proxyType, proxyAddress, proxyPort, proxyUsername, proxyPassword } = ===================================== toolkit/modules/Moat.sys.mjs ===================================== @@ -119,7 +119,7 @@ export class MoatRPC { ch.requestMethod = "HEAD"; const listener = new InternetTestResponseListener(); - await ch.asyncOpen(listener, ch); + ch.asyncOpen(listener, ch); return listener.status; } View it on GitLab: https://gitlab.torproject.org/tpo/applications/tor-browser/-/compare/70283a… -- View it on GitLab: https://gitlab.torproject.org/tpo/applications/tor-browser/-/compare/70283a… You're receiving this email because of your account on gitlab.torproject.org.
1 0
0 0
  • ← Newer
  • 1
  • ...
  • 396
  • 397
  • 398
  • 399
  • 400
  • 401
  • 402
  • ...
  • 2132
  • Older →

HyperKitty Powered by HyperKitty version 1.3.12.