tor-commits
Threads by month
- ----- 2025 -----
- 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
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
July 2021
- 17 participants
- 1545 discussions
[translation/tails-misc_completed] https://gitweb.torproject.org/translation.git/commit/?h=tails-misc_completed
by translation@torproject.org 02 Jul '21
by translation@torproject.org 02 Jul '21
02 Jul '21
commit 3cd6cf6dadfe92609c811fb50ef31b24f6ff0ea3
Author: Translation commit bot <translation(a)torproject.org>
Date: Fri Jul 2 16:15:40 2021 +0000
https://gitweb.torproject.org/translation.git/commit/?h=tails-misc_completed
---
fr.po | 2828 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 2828 insertions(+)
diff --git a/fr.po b/fr.po
new file mode 100644
index 0000000000..ad7837f888
--- /dev/null
+++ b/fr.po
@@ -0,0 +1,2828 @@
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the PACKAGE package.
+#
+# Translators:
+# bassmax, 2014-2015
+# Alex <chioubaca(a)gmail.com>, 2014
+# tneskovic <antoine_ecuador(a)yahoo.fr>, 2014
+# AO <ao(a)localizationlab.org>, 2015,2018-2021
+# apaddlingduck, 2014
+# apaddlingduck, 2014
+# Athorcis, 2015
+# Athorcis, 2015
+# Curtis Baltimore <curtisbaltimore(a)protonmail.com>, 2019-2020
+# Domiho Zannou <zannou.gery(a)gmail.com>, 2018
+# Emmanuel Simond <emmanuel.simond(a)gmail.com>, 2014
+# Emmanuel Simond <emmanuel.simond(a)gmail.com>, 2014
+# Emma Peel, 2018
+# Emma Peel, 2018
+# AO <ao(a)localizationlab.org>, 2017-2018
+# French language coordinator <french.translation(a)rbox.me>, 2015-2017
+# Gwennole Hangard <gwennole.hangard(a)gmail.com>, 2015
+# jean valjean <nihei(a)disroot.org>, 2021
+# Jean-Yves Toumit <saiolar-c(a)yahoo.fr>, 2013
+# Lidija <llazic.bgd(a)gmail.com>, 2015
+# mosira <romain.moisan(a)gmail.com>, 2014
+# Onizuka, 2013
+# Onizuka, 2013
+# PoorPockets McNewHold <poorpocketsmcnewhold(a)protonmail.ch>, 2020
+# mosira <romain.moisan(a)gmail.com>, 2014
+# Sabrina Cater <sabcat(a)gmx.fr>, 2015
+# Simon-Olivier Morneau <smorn026(a)uottawa.ca>, 2018-2019
+# Thomas Chauchefoin <thomas(a)chauchefoin.fr>, 2016
+# Thomas Prévost <thomasprevost85(a)gmail.com>, 2018
+# tneskovic <antoine_ecuador(a)yahoo.fr>, 2014
+# Towinet, 2013-2016
+# AO <ao(a)localizationlab.org>, 2015
+# xin, 2019
+# xin, 2019-2020
+msgid ""
+msgstr ""
+"Project-Id-Version: Tor Project\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2021-07-01 11:43+0200\n"
+"PO-Revision-Date: 2021-07-02 16:03+0000\n"
+"Last-Translator: AO <ao(a)localizationlab.org>\n"
+"Language-Team: French (http://www.transifex.com/otf/torproject/language/fr/)\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Language: fr\n"
+"Plural-Forms: nplurals=2; plural=(n > 1);\n"
+
+#: config/chroot_local-includes/etc/whisperback/config.py:69
+#, python-format
+msgid ""
+"<h1>Help us fix your bug!</h1>\n"
+"<p>Read <a href=\"%s\">our bug reporting instructions</a>.</p>\n"
+"<p><strong>Do not include more personal information than\n"
+"needed!</strong></p>\n"
+"<h2>About giving us an email address</h2>\n"
+"<p>\n"
+"Giving us an email address allows us to contact you to clarify the problem. This\n"
+"is needed for the vast majority of the reports we receive as most reports\n"
+"without any contact information are useless. On the other hand it also provides\n"
+"an opportunity for eavesdroppers, like your email or Internet provider, to\n"
+"confirm that you are using Tails.\n"
+"</p>\n"
+msgstr "<h1>Aidez-nous à corriger votre bogue.</h1>\n<p>Lisez <a href=\"%s\">nos instructions de signalement de bogue</a>.</p>\n<p><strong>N’incluez pas plus de renseignements personnels que nécessaire.</strong></p>\n<h2>Nous donner une adresse courriel :</h2>\n<p>\nEn nous donnant une adresse courriel, vous nous permettez de vous contacter pour clarifier le problème. Cela est nécessaire pour la vaste majorité des relevés que nous recevons, car la plupart des relevés sont inutiles sans coordonnées de contact. D’un autre côté, cela donne une occasion aux écoutes électroniques indiscrètes, telles que votre fournisseur de service Internet ou de courriel, de confirmer que vous utilisez Tails.\n</p>\n"
+
+#: config/chroot_local-includes/usr/share/tails/additional-software/configuration-window.ui:8
+#: config/chroot_local-includes/usr/src/persistence-setup/lib/Tails/Persistence/Configuration/Presets.pm:113
+#: ../config/chroot_local-includes/usr/share/applications/org.boum.tails.additional-software-config.desktop.in.h:1
+msgid "Additional Software"
+msgstr "Logiciels supplémentaires"
+
+#: config/chroot_local-includes/usr/share/tails/additional-software/configuration-window.ui:51
+msgid ""
+"You can install additional software automatically from your persistent "
+"storage when starting Tails."
+msgstr "Vous pouvez installer des logiciels supplémentaires automatiquement à partir de votre stockage persistant lors du démarrage de Tails."
+
+#: config/chroot_local-includes/usr/share/tails/additional-software/configuration-window.ui:77
+msgid ""
+"The following software is installed automatically from your persistent "
+"storage when starting Tails."
+msgstr "Les logiciels suivants sont installés automatiquement à partir de votre stockage persistant lors du démarrage de Tails."
+
+#: config/chroot_local-includes/usr/share/tails/additional-software/configuration-window.ui:135
+#: config/chroot_local-includes/usr/local/bin/tails-additional-software-config:171
+msgid ""
+"To add more, install some software using <a "
+"href=\"synaptic.desktop\">Synaptic Package Manager</a> or <a "
+"href=\"org.gnome.Terminal.desktop\">APT on the command line</a>."
+msgstr "Pour en ajouter d’autres, installez des logiciels en utilisant le <a href=\"synaptic.desktop\">gestionnaire de paquets Synaptic</a> ou <a href=\"org.gnome.Terminal.desktop\">APT en ligne de commande</a>."
+
+#: config/chroot_local-includes/usr/share/tails/additional-software/configuration-window.ui:154
+msgid "_Create persistent storage"
+msgstr "_Créer un stockage persistant"
+
+#: config/chroot_local-includes/usr/local/bin/electrum:64
+msgid "Persistence is disabled for Electrum"
+msgstr "La persistance est désactivée pour Electrum"
+
+#: config/chroot_local-includes/usr/local/bin/electrum:66
+msgid ""
+"When you reboot Tails, all of Electrum's data will be lost, including your Bitcoin wallet.\n"
+"It is strongly recommended to only run Electrum when its persistence feature is activated."
+msgstr "Quand vous redémarrerez Tails, toutes les données d’Electrum seront perdues, dont votre porte-monnaie Bitcoin.\nIl est fortement recommandé de n’utiliser Electrum qu’avec l’option de persistance activée."
+
+#: config/chroot_local-includes/usr/local/bin/electrum:67
+msgid "Do you want to start Electrum anyway?"
+msgstr "Voulez-vous quand même démarrer Electrum ?"
+
+#: config/chroot_local-includes/usr/local/bin/electrum:70
+#: config/chroot_local-includes/usr/local/sbin/unsafe-browser:43
+msgid "_Launch"
+msgstr "_Lancer"
+
+#: config/chroot_local-includes/usr/local/bin/electrum:71
+#: config/chroot_local-includes/usr/local/sbin/unsafe-browser:44
+msgid "_Exit"
+msgstr "_Quitter"
+
+#: config/chroot_local-includes/usr/src/iuk/lib/Tails/IUK/DownloadProgress.pm:59
+msgid "Unknown time"
+msgstr "Temps inconnu"
+
+#. Translators: Don't translate {count}, it's a place holder and
+#. will be replaced.
+#. y is the short form for years.
+#: config/chroot_local-includes/usr/src/iuk/lib/Tails/IUK/DownloadProgress.pm:78
+#, perl-brace-format
+msgid "1y"
+msgid_plural "{count}y"
+msgstr[0] "1 a"
+msgstr[1] "{count} a"
+
+#. Translators: Don't translate {count}, it's a place holder and
+#. will be replaced.
+#. d is the short form for days.
+#: config/chroot_local-includes/usr/src/iuk/lib/Tails/IUK/DownloadProgress.pm:82
+#, perl-brace-format
+msgid "1d"
+msgid_plural "{count}d"
+msgstr[0] "1 j"
+msgstr[1] "{count} j"
+
+#. Translators: Don't translate {count}, it's a place holder and
+#. will be replaced.
+#. h is the short form for hours;
+#: config/chroot_local-includes/usr/src/iuk/lib/Tails/IUK/DownloadProgress.pm:86
+#, perl-brace-format
+msgid "1h"
+msgid_plural "{count}h"
+msgstr[0] "1 h"
+msgstr[1] "{count} h"
+
+#. Translators: Don't translate {count}, it's a place holder and
+#. will be replaced.
+#. m is the short form for minutes;
+#: config/chroot_local-includes/usr/src/iuk/lib/Tails/IUK/DownloadProgress.pm:90
+#, perl-brace-format
+msgid "1m"
+msgid_plural "{count}m"
+msgstr[0] "1 min"
+msgstr[1] "{count} min"
+
+#. Translators: Don't translate {count}, it's a place holder and
+#. will be replaced.
+#. s is the short form for seconds;
+#: config/chroot_local-includes/usr/src/iuk/lib/Tails/IUK/DownloadProgress.pm:94
+#, perl-brace-format
+msgid "1s"
+msgid_plural "{count}s"
+msgstr[0] "1 s"
+msgstr[1] "{count} s"
+
+#. Translators: don't translate {time}, {downloaded}, {size}
+#. and {speed}, they are placeholders and will be replaced.
+#: config/chroot_local-includes/usr/src/iuk/lib/Tails/IUK/DownloadProgress.pm:139
+#, perl-brace-format
+msgid "#{time} left — {downloaded} of {size} ({speed}/sec)\n"
+msgstr "# Il reste {time} — {downloaded} de {size} ({speed}/s)\n"
+
+#. Translators: KB is the short form for kilobyte
+#: config/chroot_local-includes/usr/src/iuk/lib/Tails/IUK/Role/FormatByte.pm:33
+msgid "KB"
+msgstr "ko"
+
+#. Translators: MB is the short form for megabyte
+#: config/chroot_local-includes/usr/src/iuk/lib/Tails/IUK/Role/FormatByte.pm:35
+msgid "MB"
+msgstr "Mo"
+
+#. Translators: GB is the short form for gigabyte
+#: config/chroot_local-includes/usr/src/iuk/lib/Tails/IUK/Role/FormatByte.pm:37
+msgid "GB"
+msgstr "Go"
+
+#: config/chroot_local-includes/usr/src/iuk/lib/Tails/IUK/Role/FormatByte.pm:43
+msgid "bytes"
+msgstr "octets"
+
+#: config/chroot_local-includes/usr/src/iuk/lib/Tails/IUK/Frontend.pm:198
+#: config/chroot_local-includes/usr/src/iuk/lib/Tails/IUK/Frontend.pm:710
+#: config/chroot_local-includes/usr/src/iuk/lib/Tails/IUK/Frontend.pm:891
+msgid ""
+"For debugging information, execute the following command: sudo tails-"
+"debugging-info"
+msgstr "Pour obtenir les renseignements de débogage, exécutez la commande suivante : sudo tails-debugging-info"
+
+#: config/chroot_local-includes/usr/src/iuk/lib/Tails/IUK/Frontend.pm:290
+msgid ""
+"<b>An error occured while updating the signing key.</b>\\n\\n<b>This "
+"prevents determining whether an upgrade is available from our "
+"website.</b>\\n\\nCheck your network connection, and restart Tails to try "
+"upgrading again.\\n\\nIf the problem persists, go to "
+"file:///usr/share/doc/tails/website/doc/upgrade/error/check.en.html"
+msgstr "<b>Une erreur est survenue pendant la mise à niveau de la clé de signature.</b>\\n\\n<b>Cela empêche de déterminer si une mise à niveau est proposée sur notre site Web.</b>\\n\\nVérifiez votre connexion réseau et redémarrez Tails pour essayer de retenter la mise à niveau.\\n\\nSi le problème persiste, consultez file:///usr/share/doc/tails/website/doc/upgrade/error/check.fr.html"
+
+#: config/chroot_local-includes/usr/src/iuk/lib/Tails/IUK/Frontend.pm:304
+msgid "Error while downloading the signing key"
+msgstr "Erreur de téléchargement de la clé de signature"
+
+#: config/chroot_local-includes/usr/src/iuk/lib/Tails/IUK/Frontend.pm:316
+msgid "Error while updating the signing key"
+msgstr "Erreur de mise à jour de la clé de signature"
+
+#: config/chroot_local-includes/usr/src/iuk/lib/Tails/IUK/Frontend.pm:343
+msgid "Error while checking for upgrades"
+msgstr "Erreur de vérification de la présence de mises à niveau"
+
+#: config/chroot_local-includes/usr/src/iuk/lib/Tails/IUK/Frontend.pm:345
+msgid ""
+"<b>Could not determine whether an upgrade is available from our website.</b>\n"
+"\n"
+"Check your network connection, and restart Tails to try upgrading again.\n"
+"\n"
+"If the problem persists, go to file:///usr/share/doc/tails/website/doc/upgrade/error/check.en.html"
+msgstr "<b>Impossible de déterminer si une mise à niveau est disponible sur notre site Web.</b>\n\nVérifiez votre connexion réseau et redémarrez Tails pour essayer à nouveau de mettre à niveau.\n\nSi le problème persiste, consultez file:///usr/share/doc/tails/website/doc/upgrade/error/check.fr.html"
+
+#: config/chroot_local-includes/usr/src/iuk/lib/Tails/IUK/Frontend.pm:360
+msgid "no automatic upgrade is available from our website for this version"
+msgstr "aucune mise à niveau automatique n’est proposée sur notre site Web pour cette version"
+
+#: config/chroot_local-includes/usr/src/iuk/lib/Tails/IUK/Frontend.pm:366
+msgid "your device was not created using a USB image or Tails Installer"
+msgstr "votre périphérique n’a pas été créé en utilisant une image USB ou le programme d’installation de Tails"
+
+#: config/chroot_local-includes/usr/src/iuk/lib/Tails/IUK/Frontend.pm:371
+msgid "Tails was started from a DVD or a read-only device"
+msgstr "Tails a été démarré à partir d’un DVD ou d’un périphérique en lecture seule"
+
+#: config/chroot_local-includes/usr/src/iuk/lib/Tails/IUK/Frontend.pm:376
+msgid "there is not enough free space on the Tails system partition"
+msgstr "il n’y a pas assez d’espace libre sur la partition système de Tails"
+
+#: config/chroot_local-includes/usr/src/iuk/lib/Tails/IUK/Frontend.pm:381
+msgid "not enough memory is available on this system"
+msgstr "il n’y a pas assez de mémoire disponible sur ce système"
+
+#: config/chroot_local-includes/usr/src/iuk/lib/Tails/IUK/Frontend.pm:386
+#, perl-brace-format
+msgid "No explanation available for reason '{reason}'."
+msgstr "Il n’y a aucune explication pour la raison « {reason} »."
+
+#: config/chroot_local-includes/usr/src/iuk/lib/Tails/IUK/Frontend.pm:409
+msgid "The system is up-to-date"
+msgstr "Le système est à jour"
+
+#: config/chroot_local-includes/usr/src/iuk/lib/Tails/IUK/Frontend.pm:414
+msgid "This version of Tails is outdated, and may have security issues."
+msgstr "Cette version de Tails est obsolète et peut poser des problèmes de sécurité."
+
+#: config/chroot_local-includes/usr/src/iuk/lib/Tails/IUK/Frontend.pm:444
+#, perl-brace-format
+msgid ""
+"The available incremental upgrade requires {space_needed} of free space on "
+"Tails system partition, but only {free_space} is available."
+msgstr "La mise à niveau incrémentielle proposée exige {space_needed} d’espace libre sur la partition système de Tails, mais il n’y en a que {free_space}."
+
+#: config/chroot_local-includes/usr/src/iuk/lib/Tails/IUK/Frontend.pm:456
+#, perl-brace-format
+msgid ""
+"The available incremental upgrade requires {memory_needed} of free memory, "
+"but only {free_memory} is available."
+msgstr "La mise à niveau incrémentielle proposée exige {memory_needed} d’espace libre, mais il n’y en a que {free_memory}."
+
+#: config/chroot_local-includes/usr/src/iuk/lib/Tails/IUK/Frontend.pm:467
+msgid ""
+"An error ocurred while detecting available upgrades.\n"
+"This should not happen. Please report a bug."
+msgstr "Une erreur est survenue lors de la détection des mise à niveau proposées.\nCela ne devrait pas se produire. Veuillez signaler un bogue."
+
+#: config/chroot_local-includes/usr/src/iuk/lib/Tails/IUK/Frontend.pm:470
+#: config/chroot_local-includes/usr/src/iuk/lib/Tails/IUK/Frontend.pm:489
+msgid "Error while detecting available upgrades"
+msgstr "Erreur de détection des mises à niveau proposées"
+
+#: config/chroot_local-includes/usr/src/iuk/lib/Tails/IUK/Frontend.pm:485
+msgid ""
+"An incremental upgrade is available, but no full upgrade is.\n"
+"This should not happen. Please report a bug."
+msgstr "Une mise à niveau incrémentielle est proposée, mais aucune mise à niveau complète ne l’est.\nCela ne devrait pas se produire. Veuillez signaler un bogue."
+
+#: config/chroot_local-includes/usr/src/iuk/lib/Tails/IUK/Frontend.pm:498
+#, perl-brace-format
+msgid ""
+"<b>You should upgrade to {name} {version}.</b>\n"
+"\n"
+"For more information about this new version, go to {details_url}\n"
+"\n"
+"We recommend you close all other applications during the upgrade.\n"
+"Downloading the upgrade might take a long time, from several minutes to a few hours.\n"
+"\n"
+"Download size: {size}\n"
+"\n"
+"Do you want to upgrade now?"
+msgstr "<b>Vous devriez mettre à niveau vers {name} {version}.</b>\n\nPour plus de précisions sur cette nouvelle version, visitez {details_url}\n\nNous vous recommandons de fermer toutes les applications pendant la mise à niveau.\nLe téléchargement de la mise à niveau pourrait être long, de plusieurs minutes à quelques heures.\n\nTaille du téléchargement : {size}\n\nVoulez-vous mettre à niveau maintenant ?"
+
+#: config/chroot_local-includes/usr/src/iuk/lib/Tails/IUK/Frontend.pm:511
+msgid "Upgrade available"
+msgstr "Une mise à niveau est proposée"
+
+#: config/chroot_local-includes/usr/src/iuk/lib/Tails/IUK/Frontend.pm:512
+msgid "Upgrade now"
+msgstr "Mettre à niveau maintenant"
+
+#: config/chroot_local-includes/usr/src/iuk/lib/Tails/IUK/Frontend.pm:513
+msgid "Upgrade later"
+msgstr "Mettre à niveau plus tard"
+
+#: config/chroot_local-includes/usr/src/iuk/lib/Tails/IUK/Frontend.pm:520
+#, perl-brace-format
+msgid ""
+"<b>You should do a manual upgrade to {name} {version}.</b>\n"
+"\n"
+"For more information about this new version, go to {details_url}\n"
+"\n"
+"It is not possible to automatically upgrade your device to this new version: {explanation}.\n"
+"\n"
+"To learn how to do a manual upgrade, go to {manual_upgrade_url}"
+msgstr "<b>Vous devriez mettre à niveau manuellement vers {name} {version}.</b>\n\nPour plus de précisions sur cette nouvelle version, visitez {details_url}.\n\nIl n’est pas possible de mettre votre appareil automatiquement à niveau vers cette nouvelle version : {explanation}.\n\nPour apprendre à faire une mise à niveau manuelle, visitez {manual_upgrade_url}"
+
+#: config/chroot_local-includes/usr/src/iuk/lib/Tails/IUK/Frontend.pm:531
+msgid "New version available"
+msgstr "Une nouvelle version est proposée"
+
+#: config/chroot_local-includes/usr/src/iuk/lib/Tails/IUK/Frontend.pm:612
+msgid "Downloading upgrade"
+msgstr "Téléchargement de la mise à niveau"
+
+#: config/chroot_local-includes/usr/src/iuk/lib/Tails/IUK/Frontend.pm:614
+#, perl-brace-format
+msgid "Downloading the upgrade to {name} {version}..."
+msgstr "Téléchargement de la mise à niveau vers {name} {version}…"
+
+#: config/chroot_local-includes/usr/src/iuk/lib/Tails/IUK/Frontend.pm:703
+msgid ""
+"<b>The upgrade could not be downloaded.</b>\\n\\nCheck your network "
+"connection, and restart Tails to try upgrading again.\\n\\nIf the problem "
+"persists, go to "
+"file:///usr/share/doc/tails/website/doc/upgrade/error/download.en.html"
+msgstr "<b>La mise à niveau n’a pas pu être téléchargée.<b>\\n\\nVérifiez votre connexion réseau et redémarrez Tails pour retenter de mettre à niveau.\\n\\nSi le problème persiste, consultez file:///usr/share/doc/tails/website/doc/upgrade/error/download.fr.html"
+
+#: config/chroot_local-includes/usr/src/iuk/lib/Tails/IUK/Frontend.pm:714
+#: config/chroot_local-includes/usr/src/iuk/lib/Tails/IUK/Frontend.pm:729
+msgid "Error while downloading the upgrade"
+msgstr "Erreur de téléchargement de la mise à niveau"
+
+#: config/chroot_local-includes/usr/src/iuk/lib/Tails/IUK/Frontend.pm:724
+#, perl-brace-format
+msgid ""
+"Output file '{output_file}' does not exist, but tails-iuk-get-target-file "
+"did not complain. Please report a bug."
+msgstr "Le fichier de sortie « {output_file} » n’existe pas, mais tails-iuk-get-target-file ne s’en est pas plaint. Veuillez signaler un bogue."
+
+#: config/chroot_local-includes/usr/src/iuk/lib/Tails/IUK/Frontend.pm:740
+msgid "Error while creating temporary downloading directory"
+msgstr "Erreur de création du répertoire temporaire de téléchargement"
+
+#: config/chroot_local-includes/usr/src/iuk/lib/Tails/IUK/Frontend.pm:743
+msgid "Failed to create temporary download directory"
+msgstr "Échec de création du répertoire temporaire de téléchargement"
+
+#: config/chroot_local-includes/usr/src/iuk/lib/Tails/IUK/Frontend.pm:767
+msgid ""
+"<b>Could not choose a download server.</b>\n"
+"\n"
+"This should not happen. Please report a bug."
+msgstr "<b>Impossible de choisir un serveur de téléchargement.</b>\n\nCela ne devrait pas arriver. Veuillez signaler un bogue."
+
+#: config/chroot_local-includes/usr/src/iuk/lib/Tails/IUK/Frontend.pm:770
+msgid "Error while choosing a download server"
+msgstr "Erreur de sélection d’un serveur de téléchargement"
+
+#: config/chroot_local-includes/usr/src/iuk/lib/Tails/IUK/Frontend.pm:784
+msgid ""
+"The upgrade was successfully downloaded.\n"
+"\n"
+"The network connection will be disabled when applying the upgrade.\n"
+"\n"
+"Please save your work and close all other applications."
+msgstr "La mise à niveau a été téléchargée avec succès.\n\nLa connexion réseau sera désactivée pendant l’application de la mise à niveau.\n\nVeuillez enregistrer vos travaux et fermer toutes autres applications."
+
+#: config/chroot_local-includes/usr/src/iuk/lib/Tails/IUK/Frontend.pm:789
+msgid "Upgrade successfully downloaded"
+msgstr "La mise à niveau a été téléchargée avec succès"
+
+#: config/chroot_local-includes/usr/src/iuk/lib/Tails/IUK/Frontend.pm:790
+msgid "Apply upgrade"
+msgstr "Appliquer la mise à niveau"
+
+#: config/chroot_local-includes/usr/src/iuk/lib/Tails/IUK/Frontend.pm:797
+msgid ""
+"<b>Your Tails device was successfully upgraded.</b>\n"
+"\n"
+"Some security features were temporarily disabled.\n"
+"You should restart Tails on the new version as soon as possible.\n"
+"\n"
+"Do you want to restart now?"
+msgstr "<b>Votre périphérique Tails a été mis à niveau avec succès.</b>\n\nQuelques fonctionnalités de sécurité ont été temporairement désactivées..\nVous devriez redémarrer Tails sur la nouvelle version dès que possible.\n\nVoulez-vous redémarrer maintenant ?"
+
+#: config/chroot_local-includes/usr/src/iuk/lib/Tails/IUK/Frontend.pm:802
+msgid "Restart Tails"
+msgstr "Redémarrer Tails"
+
+#: config/chroot_local-includes/usr/src/iuk/lib/Tails/IUK/Frontend.pm:803
+msgid "Restart now"
+msgstr "Redémarrer maintenant"
+
+#: config/chroot_local-includes/usr/src/iuk/lib/Tails/IUK/Frontend.pm:804
+msgid "Restart later"
+msgstr "Redémarrer plus tard"
+
+#: config/chroot_local-includes/usr/src/iuk/lib/Tails/IUK/Frontend.pm:814
+msgid "Error while restarting the system"
+msgstr "Erreur de redémarrage du système"
+
+#: config/chroot_local-includes/usr/src/iuk/lib/Tails/IUK/Frontend.pm:815
+msgid "Failed to restart the system"
+msgstr "Échec de redémarrage du système"
+
+#: config/chroot_local-includes/usr/src/iuk/lib/Tails/IUK/Frontend.pm:828
+msgid "Error while shutting down the network"
+msgstr "Erreur de désactivation du réseau"
+
+#: config/chroot_local-includes/usr/src/iuk/lib/Tails/IUK/Frontend.pm:829
+msgid "Failed to shutdown network"
+msgstr "Échec d’arrêt du réseau"
+
+#: config/chroot_local-includes/usr/src/iuk/lib/Tails/IUK/Frontend.pm:839
+msgid "Error while cancelling the upgrade download"
+msgstr "Erreur d’annulation du téléchargement de la mise à niveau"
+
+#: config/chroot_local-includes/usr/src/iuk/lib/Tails/IUK/Frontend.pm:840
+msgid "Failed to cancel the upgrade download"
+msgstr "Échec d’annulation du téléchargement de la mise à niveau"
+
+#: config/chroot_local-includes/usr/src/iuk/lib/Tails/IUK/Frontend.pm:846
+msgid "Upgrading the system"
+msgstr "Mise à jour du système"
+
+#: config/chroot_local-includes/usr/src/iuk/lib/Tails/IUK/Frontend.pm:848
+msgid ""
+"<b>Your Tails device is being upgraded...</b>\n"
+"\n"
+"For security reasons, the network connection is now disabled."
+msgstr "</b>Votre périphérique Tails est en cours de mise à niveau…</b>\n\nPour des raisons de sécurité, la connexion au réseau est actuellement désactivée."
+
+#: config/chroot_local-includes/usr/src/iuk/lib/Tails/IUK/Frontend.pm:885
+msgid ""
+"<b>An error occured while installing the upgrade.</b>\\n\\nYour Tails device"
+" needs to be repaired and might be unable to restart.\\n\\nPlease follow the"
+" instructions at "
+"file:///usr/share/doc/tails/website/doc/upgrade/error/install.en.html"
+msgstr "<b>Une erreur est survenue durant l’installation de la mise à niveau.</b>\\n\\nVotre périphérique Tails doit être réparé et pourrait ne pas redémarrer.\\n\\nVeuillez suivre les instructions sur file:///usr/share/doc/tails/website/doc/upgrade/error/install.fr.html"
+
+#: config/chroot_local-includes/usr/src/iuk/lib/Tails/IUK/Frontend.pm:895
+msgid "Error while installing the upgrade"
+msgstr "Erreur d’installation de la mise à niveau"
+
+#: config/chroot_local-includes/usr/lib/python3/dist-packages/tailsgreeter/ui/add_settings_dialog.py:32
+msgid "Additional Settings"
+msgstr "Paramètres supplémentaires"
+
+#: config/chroot_local-includes/usr/lib/python3/dist-packages/tailsgreeter/ui/add_settings_dialog.py:40
+#: config/chroot_local-includes/usr/lib/python3/dist-packages/tails_installer/gui.py:581
+#: config/chroot_local-includes/usr/local/sbin/tails-additional-software:366
+#: config/chroot_local-includes/usr/local/bin/tails-screen-locker:119
+#: config/chroot_local-includes/usr/bin/tor-browser:51
+msgid "Cancel"
+msgstr "Annuler"
+
+#: config/chroot_local-includes/usr/lib/python3/dist-packages/tailsgreeter/ui/add_settings_dialog.py:46
+msgid "Add"
+msgstr "Ajouter"
+
+#: config/chroot_local-includes/usr/lib/python3/dist-packages/tailsgreeter/ui/add_settings_dialog.py:54
+msgid "Back"
+msgstr "Précédent"
+
+#: config/chroot_local-includes/usr/lib/python3/dist-packages/tailsgreeter/ui/additional_settings.py:64
+msgid "_Administration Password"
+msgstr "_Mot de passe d’administration"
+
+#: config/chroot_local-includes/usr/lib/python3/dist-packages/tailsgreeter/ui/additional_settings.py:187
+msgid "_MAC Address Anonymization"
+msgstr "Anonymisation de l’adresse _MAC"
+
+#: config/chroot_local-includes/usr/lib/python3/dist-packages/tailsgreeter/ui/additional_settings.py:250
+msgid "_Offline Mode"
+msgstr "Mode _Hors ligne"
+
+#: config/chroot_local-includes/usr/lib/python3/dist-packages/tailsgreeter/ui/additional_settings.py:259
+#: ../config/chroot_local-includes/usr/share/tails/greeter/additional_settings.ui.in:413
+msgid "Enable networking (default)"
+msgstr "Activer la mise en réseau (par défaut)"
+
+#: config/chroot_local-includes/usr/lib/python3/dist-packages/tailsgreeter/ui/additional_settings.py:261
+#: ../config/chroot_local-includes/usr/share/tails/greeter/additional_settings.ui.in:459
+msgid "Disable all networking"
+msgstr "Désactiver la mise en réseau"
+
+#: config/chroot_local-includes/usr/lib/python3/dist-packages/tailsgreeter/ui/additional_settings.py:316
+msgid "_Network Connection"
+msgstr "Connexion _réseau"
+
+#: config/chroot_local-includes/usr/lib/python3/dist-packages/tailsgreeter/ui/additional_settings.py:324
+msgid "Obsolete"
+msgstr "Désuet"
+
+#: config/chroot_local-includes/usr/lib/python3/dist-packages/tailsgreeter/ui/additional_settings.py:339
+msgid "_Unsafe Browser"
+msgstr "Navigateur _non sécurisé"
+
+#: config/chroot_local-includes/usr/lib/python3/dist-packages/tailsgreeter/ui/additional_settings.py:348
+msgid "Enabled"
+msgstr "Activé"
+
+#: config/chroot_local-includes/usr/lib/python3/dist-packages/tailsgreeter/ui/additional_settings.py:350
+msgid "Disabled (default)"
+msgstr "Désactivé (par défaut)"
+
+#: config/chroot_local-includes/usr/lib/python3/dist-packages/tailsgreeter/ui/additional_settings.py:401
+msgid "On (default)"
+msgstr "Activé (par défaut)"
+
+#: config/chroot_local-includes/usr/lib/python3/dist-packages/tailsgreeter/ui/additional_settings.py:403
+msgid "On"
+msgstr "Activé"
+
+#: config/chroot_local-includes/usr/lib/python3/dist-packages/tailsgreeter/ui/additional_settings.py:405
+msgid "Off"
+msgstr "Désactivé"
+
+#: config/chroot_local-includes/usr/lib/python3/dist-packages/tailsgreeter/ui/additional_settings.py:407
+msgid "Off (default)"
+msgstr "Désactivé (par défaut)"
+
+#: config/chroot_local-includes/usr/lib/python3/dist-packages/tailsgreeter/settings/persistence.py:91
+#, python-brace-format
+msgid ""
+"live-persist failed with return code {returncode}:\n"
+"{stderr}"
+msgstr "Échec de live-persist avec le code de retour {returncode}:\n{stderr}"
+
+#: config/chroot_local-includes/usr/lib/python3/dist-packages/tailsgreeter/settings/persistence.py:122
+#: config/chroot_local-includes/usr/lib/python3/dist-packages/tailsgreeter/settings/persistence.py:139
+#, python-brace-format
+msgid ""
+"cryptsetup failed with return code {returncode}:\n"
+"{stdout}\n"
+"{stderr}"
+msgstr "cryptsetup a échoué avec le code de retour {returncode} :\n{stdout}\n{stderr}"
+
+#: config/chroot_local-includes/usr/lib/python3/dist-packages/tailsgreeter/settings/persistence.py:153
+#, python-brace-format
+msgid ""
+"live-persist failed with return code {returncode}:\n"
+"{stdout}\n"
+"{stderr}"
+msgstr "Échec de live-persist avec le code de retour {returncode}:\n{stdout}\n{stderr}"
+
+#: config/chroot_local-includes/usr/lib/python3/dist-packages/tailsgreeter/settings/persistence.py:167
+#, python-brace-format
+msgid ""
+"umount failed with return code {returncode}:\n"
+"{stdout}\n"
+"{stderr}"
+msgstr "umount a échoué avec le code de retour {returncode} :\n{stdout}\n{stderr}"
+
+#: config/chroot_local-includes/usr/lib/python3/dist-packages/tailsgreeter/ui/persistent_storage.py:67
+msgid "Unlocking…"
+msgstr "Déverrouillage…"
+
+#: config/chroot_local-includes/usr/lib/python3/dist-packages/tailsgreeter/ui/persistent_storage.py:95
+#: ../config/chroot_local-includes/usr/share/tails/greeter/main.ui.in:394
+msgid "Unlock"
+msgstr "Déverrouiller"
+
+#: config/chroot_local-includes/usr/lib/python3/dist-packages/tailsgreeter/ui/persistent_storage.py:100
+#: ../config/chroot_local-includes/usr/share/tails/greeter/main.ui.in:40
+msgid "Cannot unlock encrypted storage with this passphrase."
+msgstr "Cette phrase de passe ne permet pas de déverrouiller le stockage chiffré."
+
+#: config/chroot_local-includes/usr/lib/python3/dist-packages/tailsgreeter/ui/region_settings.py:164
+msgid "_Language"
+msgstr "_Langue"
+
+#: config/chroot_local-includes/usr/lib/python3/dist-packages/tailsgreeter/ui/region_settings.py:207
+msgid "_Formats"
+msgstr "_Formats"
+
+#: config/chroot_local-includes/usr/lib/python3/dist-packages/tailsgreeter/ui/region_settings.py:244
+msgid "_Keyboard Layout"
+msgstr "Disposition du _clavier"
+
+#: config/chroot_local-includes/usr/lib/python3/dist-packages/tails_installer/creator.py:261
+#, python-format
+msgid "Unable to write on %(device)s, skipping."
+msgstr "Impossible d’écrire sur %(device)s, passage à l’étape suivante."
+
+#: config/chroot_local-includes/usr/lib/python3/dist-packages/tails_installer/creator.py:294
+#, python-format
+msgid ""
+"Some partitions of the target device %(device)s are mounted. They will be "
+"unmounted before starting the installation process."
+msgstr "Certaines partitions du périphérique cible %(device)s sont montées. Elles seront démontées avant de lancer le processus d’installation."
+
+#: config/chroot_local-includes/usr/lib/python3/dist-packages/tails_installer/creator.py:303
+msgid "Extracting live image to the target device..."
+msgstr "Extraction de l’image live vers le périphérique cible…"
+
+#: config/chroot_local-includes/usr/lib/python3/dist-packages/tails_installer/creator.py:310
+#, python-format
+msgid "Wrote to device at %(speed)d MB/sec"
+msgstr "Écriture sur le périphérique effectuée à %(speed)d Mo/sec"
+
+#: config/chroot_local-includes/usr/lib/python3/dist-packages/tails_installer/creator.py:408
+#, python-format
+msgid ""
+"There was a problem executing the following command: `%(command)s`.\n"
+"A more detailed error log has been written to \"%(filename)s\"."
+msgstr "Un problème est survenu lors de l’exécution de la commande suivante : `%(command)s`.\nUn journal d’erreurs plus détaillé a été écrit dans le fichier `%(filename)s`."
+
+#: config/chroot_local-includes/usr/lib/python3/dist-packages/tails_installer/creator.py:424
+#, python-format
+msgid ""
+"Not enough free space on device.\n"
+"%(iso_size)dMB ISO + %(overlay_size)dMB overlay > %(free_space)dMB free space"
+msgstr "Il manque d’espace libre sur le périphérique.\nISO de %(iso_size)d Mo + %(overlay_size)d Mo réservé pour la persistance > %(free_space)d Mo d’espace libre"
+
+#: config/chroot_local-includes/usr/lib/python3/dist-packages/tails_installer/creator.py:433
+#, python-format
+msgid "Creating %sMB persistent overlay"
+msgstr "Création de l’espace réservé pour la persistance de %s Mo"
+
+#: config/chroot_local-includes/usr/lib/python3/dist-packages/tails_installer/creator.py:483
+#, python-format
+msgid "Unable to copy %(infile)s to %(outfile)s: %(message)s"
+msgstr "Impossible de copier %(infile)s vers %(outfile)s : %(message)s"
+
+#: config/chroot_local-includes/usr/lib/python3/dist-packages/tails_installer/creator.py:497
+msgid "Removing existing Tails system"
+msgstr "Suppression du système Tails existant"
+
+#: config/chroot_local-includes/usr/lib/python3/dist-packages/tails_installer/creator.py:507
+#, python-format
+msgid "Unable to remove file from previous Tails system: %(message)s"
+msgstr "Impossible de supprimer le fichier du système Tails précédent : %(message)s"
+
+#: config/chroot_local-includes/usr/lib/python3/dist-packages/tails_installer/creator.py:514
+#, python-format
+msgid "Unable to chmod %(file)s: %(message)s"
+msgstr "Impossible de changer les droits (chmod) de %(file)s : %(message)s"
+
+#: config/chroot_local-includes/usr/lib/python3/dist-packages/tails_installer/creator.py:521
+#, python-format
+msgid "Unable to remove directory from previous Tails system: %(message)s"
+msgstr "Impossible de supprimer le répertoire du système Tails précédent : %(message)s"
+
+#: config/chroot_local-includes/usr/lib/python3/dist-packages/tails_installer/creator.py:569
+#, python-format
+msgid "Cannot find device %s"
+msgstr "Le périphérique %s est introuvable"
+
+#: config/chroot_local-includes/usr/lib/python3/dist-packages/tails_installer/creator.py:619
+#: config/chroot_local-includes/usr/lib/python3/dist-packages/tails_installer/creator.py:836
+msgid "Unknown filesystem. Your device may need to be reformatted."
+msgstr "Le système de fichiers est inconnu. Votre périphérique doit peut-être être reformaté."
+
+#: config/chroot_local-includes/usr/lib/python3/dist-packages/tails_installer/creator.py:622
+#: config/chroot_local-includes/usr/lib/python3/dist-packages/tails_installer/creator.py:839
+#, python-format
+msgid "Unsupported filesystem: %s"
+msgstr "Système de fichiers non pris en charge : %s"
+
+#: config/chroot_local-includes/usr/lib/python3/dist-packages/tails_installer/creator.py:640
+#, python-format
+msgid "Unknown GLib exception while trying to mount device: %(message)s"
+msgstr "Exception GLib inconnue lors de la tentative de montage du périphérique : %(message)s"
+
+#: config/chroot_local-includes/usr/lib/python3/dist-packages/tails_installer/creator.py:645
+#, python-format
+msgid "Unable to mount device: %(message)s"
+msgstr "Impossible de monter le périphérique : %(message)s"
+
+#: config/chroot_local-includes/usr/lib/python3/dist-packages/tails_installer/creator.py:650
+msgid "No mount points found"
+msgstr "Aucun point de montage n’a été trouvé"
+
+#: config/chroot_local-includes/usr/lib/python3/dist-packages/tails_installer/creator.py:661
+#, python-format
+msgid "Entering unmount_device for \"%(device)s\""
+msgstr "Saisie de unmount_device pour « %(device)s »"
+
+#: config/chroot_local-includes/usr/lib/python3/dist-packages/tails_installer/creator.py:670
+#, python-format
+msgid "Unmounting mounted filesystems on \"%(device)s\""
+msgstr "Démontage des systèmes de fichiers montés sur « %(device)s »"
+
+#: config/chroot_local-includes/usr/lib/python3/dist-packages/tails_installer/creator.py:674
+#, python-format
+msgid "Unmounting \"%(udi)s\" on \"%(device)s\""
+msgstr "Démontage de « %(udi)s » sur « %(device)s »"
+
+#: config/chroot_local-includes/usr/lib/python3/dist-packages/tails_installer/creator.py:685
+#, python-format
+msgid "Mount %s exists after unmounting"
+msgstr "Le montage %s existe après démontage"
+
+#: config/chroot_local-includes/usr/lib/python3/dist-packages/tails_installer/creator.py:698
+#, python-format
+msgid "Partitioning device %(device)s"
+msgstr "Partitionnement du périphérique %(device)s"
+
+#: config/chroot_local-includes/usr/lib/python3/dist-packages/tails_installer/creator.py:821
+#, python-format
+msgid "Unsupported device '%(device)s', please report a bug."
+msgstr "Périphérique « %(device)s » non pris en charge, veuillez signaler le bogue."
+
+#: config/chroot_local-includes/usr/lib/python3/dist-packages/tails_installer/creator.py:824
+msgid "Trying to continue anyway."
+msgstr "Nous tentons de poursuivre quand même."
+
+#: config/chroot_local-includes/usr/lib/python3/dist-packages/tails_installer/creator.py:833
+msgid "Verifying filesystem..."
+msgstr "Vérification du système de fichiers…"
+
+#: config/chroot_local-includes/usr/lib/python3/dist-packages/tails_installer/creator.py:857
+#, python-format
+msgid "Unable to change volume label: %(message)s"
+msgstr "Impossible de changer l’étiquette du volume : %(message)s"
+
+#: config/chroot_local-includes/usr/lib/python3/dist-packages/tails_installer/creator.py:862
+msgid "Installing bootloader..."
+msgstr "Installation du chargeur de démarrage…"
+
+#: config/chroot_local-includes/usr/lib/python3/dist-packages/tails_installer/creator.py:869
+#, python-format
+msgid "Removing %(file)s"
+msgstr "Suppression de %(file)s"
+
+#: config/chroot_local-includes/usr/lib/python3/dist-packages/tails_installer/creator.py:951
+#, python-format
+msgid "%s already bootable"
+msgstr "%s est déjà amorçable"
+
+#: config/chroot_local-includes/usr/lib/python3/dist-packages/tails_installer/creator.py:971
+msgid "Unable to find partition"
+msgstr "Impossible de trouver la partition"
+
+#: config/chroot_local-includes/usr/lib/python3/dist-packages/tails_installer/creator.py:990
+#, python-format
+msgid "Formatting %(device)s as FAT32"
+msgstr "Formatage de %(device)s en FAT32"
+
+#: config/chroot_local-includes/usr/lib/python3/dist-packages/tails_installer/creator.py:1053
+#, python-format
+msgid "Reading extracted MBR from %s"
+msgstr "Lecture du MBR extrait de %s"
+
+#: config/chroot_local-includes/usr/lib/python3/dist-packages/tails_installer/creator.py:1057
+#, python-format
+msgid "Could not read the extracted MBR from %(path)s"
+msgstr "Impossible de lire le MBR extrait de %(path)s"
+
+#: config/chroot_local-includes/usr/lib/python3/dist-packages/tails_installer/creator.py:1070
+#: config/chroot_local-includes/usr/lib/python3/dist-packages/tails_installer/creator.py:1071
+#, python-format
+msgid "Resetting Master Boot Record of %s"
+msgstr "Réinitialisation de l’enregistrement d’amorçage maître (MBR) de %s"
+
+#: config/chroot_local-includes/usr/lib/python3/dist-packages/tails_installer/creator.py:1076
+msgid "Drive is a loopback, skipping MBR reset"
+msgstr "Le périphérique est une boucle, la réinitialisation du MBR sera ignorée"
+
+#: config/chroot_local-includes/usr/lib/python3/dist-packages/tails_installer/creator.py:1080
+msgid "Synchronizing data on disk..."
+msgstr "Synchronisation des données sur le disque…"
+
+#: config/chroot_local-includes/usr/lib/python3/dist-packages/tails_installer/gui.py:146
+msgid ""
+"Error: Cannot set the label or obtain the UUID of your device. Unable to "
+"continue."
+msgstr "Erreur : impossible de définir l’étiquette ou d’obtenir l’UUID de votre périphérique. Impossible de poursuivre."
+
+#: config/chroot_local-includes/usr/lib/python3/dist-packages/tails_installer/gui.py:180
+#, python-format
+msgid "Installation complete! (%s)"
+msgstr "L’installation est terminée. (%s)"
+
+#: config/chroot_local-includes/usr/lib/python3/dist-packages/tails_installer/gui.py:185
+msgid "Tails installation failed!"
+msgstr "L’installation de Tails a échoué."
+
+#: config/chroot_local-includes/usr/lib/python3/dist-packages/tails_installer/gui.py:274
+#: ../config/chroot_local-includes/usr/share/applications/tails-installer.desktop.in.h:1
+msgid "Tails Installer"
+msgstr "Programme d’installation de Tails"
+
+#: config/chroot_local-includes/usr/lib/python3/dist-packages/tails_installer/gui.py:316
+#: ../config/chroot_local-includes/usr/share/tails-installer/tails-installer.ui.in:163
+msgid "Clone the current Tails"
+msgstr "Cloner le Tails utilisé actuellement"
+
+#: config/chroot_local-includes/usr/lib/python3/dist-packages/tails_installer/gui.py:323
+#: ../config/chroot_local-includes/usr/share/tails-installer/tails-installer.ui.in:184
+msgid "Use a downloaded Tails ISO image"
+msgstr "Utiliser une image ISO Tails téléchargée"
+
+#: config/chroot_local-includes/usr/lib/python3/dist-packages/tails_installer/gui.py:361
+#: config/chroot_local-includes/usr/lib/python3/dist-packages/tails_installer/gui.py:657
+msgid "Upgrade"
+msgstr "Mettre à niveau"
+
+#: config/chroot_local-includes/usr/lib/python3/dist-packages/tails_installer/gui.py:362
+msgid "Manual Upgrade Instructions"
+msgstr "Instructions de mise à niveau manuelle"
+
+#: config/chroot_local-includes/usr/lib/python3/dist-packages/tails_installer/gui.py:371
+#: config/chroot_local-includes/usr/lib/python3/dist-packages/tails_installer/gui.py:569
+#: config/chroot_local-includes/usr/lib/python3/dist-packages/tails_installer/gui.py:634
+#: ../config/chroot_local-includes/usr/share/tails-installer/tails-installer.ui.in:358
+msgid "Install"
+msgstr "Installer"
+
+#: config/chroot_local-includes/usr/lib/python3/dist-packages/tails_installer/gui.py:373
+#: ../config/chroot_local-includes/usr/share/tails-installer/tails-installer.ui.in:131
+msgid "Installation Instructions"
+msgstr "Instructions d’installation"
+
+#: config/chroot_local-includes/usr/lib/python3/dist-packages/tails_installer/gui.py:380
+#, python-format
+msgid "%(size)s %(vendor)s %(model)s device (%(device)s)"
+msgstr "Périphérique %(vendor)s %(model)s %(size)s (%(device)s)"
+
+#: config/chroot_local-includes/usr/lib/python3/dist-packages/tails_installer/gui.py:392
+msgid "No ISO image selected"
+msgstr "Aucune image ISO n’a été sélectionnée"
+
+#: config/chroot_local-includes/usr/lib/python3/dist-packages/tails_installer/gui.py:393
+msgid "Please select a Tails ISO image."
+msgstr "Veuillez sélectionner une image ISO de Tails."
+
+#: config/chroot_local-includes/usr/lib/python3/dist-packages/tails_installer/gui.py:435
+msgid "No device suitable to install Tails could be found"
+msgstr "Aucun périphérique adapté n’a été trouvé pour installer Tails"
+
+#: config/chroot_local-includes/usr/lib/python3/dist-packages/tails_installer/gui.py:437
+#, python-format
+msgid "Please plug a USB flash drive or SD card of at least %0.1f GB."
+msgstr "Veuillez brancher une clé USB ou une carte SD d’au moins %0.1f Go."
+
+#: config/chroot_local-includes/usr/lib/python3/dist-packages/tails_installer/gui.py:468
+#, python-format
+msgid ""
+"The USB stick \"%(pretty_name)s\" is configured as non-removable by its "
+"manufacturer and Tails will fail to start from it. Please try installing on "
+"a different model."
+msgstr "La clé USB « %(pretty_name)s » est configurée comme non amovible par son fabricant et le démarrage de Tails échouera sur cette clé. Veuillez tenter d’installer Tails sur un modèle différent."
+
+#: config/chroot_local-includes/usr/lib/python3/dist-packages/tails_installer/gui.py:478
+#, python-format
+msgid ""
+"The device \"%(pretty_name)s\" is too small to install Tails (at least "
+"%(size)s GB is required)."
+msgstr "Le périphérique « %(pretty_name)s » est trop petit pour installer Tails (au moins %(size)s Go sont exigés)."
+
+#: config/chroot_local-includes/usr/lib/python3/dist-packages/tails_installer/gui.py:491
+#, python-format
+msgid ""
+"To upgrade device \"%(pretty_name)s\" from this Tails, you need to use a downloaded Tails ISO image:\n"
+"%(dl_url)s"
+msgstr "Pour mettre à niveau le périphérique « %(pretty_name)s » à partir de ce Tails, vous devez utiliser une image ISO Tails téléchargée :\n%(dl_url)s"
+
+#: config/chroot_local-includes/usr/lib/python3/dist-packages/tails_installer/gui.py:513
+msgid "An error happened while installing Tails"
+msgstr "Une erreur est survenue lors de l’installation de Tails"
+
+#: config/chroot_local-includes/usr/lib/python3/dist-packages/tails_installer/gui.py:564
+msgid "Installation complete!"
+msgstr "L’installation est terminée."
+
+#: config/chroot_local-includes/usr/lib/python3/dist-packages/tails_installer/gui.py:617
+msgid "Unable to mount device"
+msgstr "Impossible de monter le périphérique"
+
+#: config/chroot_local-includes/usr/lib/python3/dist-packages/tails_installer/gui.py:624
+#: config/chroot_local-includes/usr/lib/python3/dist-packages/tails_installer/gui.py:656
+msgid "Confirm the target USB stick"
+msgstr "Confirmer la clé USB cible"
+
+#: config/chroot_local-includes/usr/lib/python3/dist-packages/tails_installer/gui.py:625
+#, python-format
+msgid ""
+"%(size)s %(vendor)s %(model)s device (%(device)s)\n"
+"\n"
+"All data on this USB stick will be lost."
+msgstr "Périphérique %(vendor)s %(model)s %(size)s (%(device)s)\n\nToutes les données de la clé USB seront perdues."
+
+#: config/chroot_local-includes/usr/lib/python3/dist-packages/tails_installer/gui.py:643
+#, python-format
+msgid "%(parent_size)s %(vendor)s %(model)s device (%(device)s)"
+msgstr "Périphérique %(vendor)s %(model)s %(parent_size)s (%(device)s)"
+
+#: config/chroot_local-includes/usr/lib/python3/dist-packages/tails_installer/gui.py:651
+msgid ""
+"\n"
+"\n"
+"The persistent storage on this USB stick will be preserved."
+msgstr "\n\nLe stockage persistant de la clé USB sera conservé."
+
+#: config/chroot_local-includes/usr/lib/python3/dist-packages/tails_installer/gui.py:652
+#, python-format
+msgid "%(description)s%(persistence_message)s"
+msgstr "%(description)s%(persistence_message)s"
+
+#: config/chroot_local-includes/usr/lib/python3/dist-packages/tails_installer/gui.py:688
+msgid ""
+"The selected file is unreadable. Please fix its permissions or select "
+"another file."
+msgstr "Le fichier sélectionné est illisible. Veuillez changer ses droits ou sélectionner un autre fichier."
+
+#: config/chroot_local-includes/usr/lib/python3/dist-packages/tails_installer/gui.py:694
+msgid ""
+"Unable to use the selected file. You may have better luck if you move your "
+"ISO to the root of your drive (ie: C:\\)"
+msgstr "Impossible d’utiliser le fichier sélectionné. Vous pourriez avoir plus de chance en déplaçant l’ISO sur la racine de votre disque (c.-à-d : C:\\)"
+
+#: config/chroot_local-includes/usr/lib/python3/dist-packages/tails_installer/gui.py:700
+#, python-format
+msgid "%(filename)s selected"
+msgstr "%(filename)s est sélectionné"
+
+#: config/chroot_local-includes/usr/lib/python3/dist-packages/tails_installer/source.py:31
+msgid "Unable to find Tails on ISO"
+msgstr "Impossible de trouver Tails sur l’ISO"
+
+#: config/chroot_local-includes/usr/lib/python3/dist-packages/tails_installer/source.py:37
+#, python-format
+msgid "Could not guess underlying block device: %s"
+msgstr "Impossible de trouver le périphérique de bloc sous-jacent : %s"
+
+#: config/chroot_local-includes/usr/lib/python3/dist-packages/tails_installer/source.py:52
+#, python-format
+msgid ""
+"There was a problem executing `%(cmd)s`.\n"
+"%(out)s\n"
+"%(err)s"
+msgstr "Un problème est survenu lors de l’exécution de `%(cmd)s`.\n%(out)s\n%(err)s"
+
+#: config/chroot_local-includes/usr/lib/python3/dist-packages/tails_installer/source.py:64
+#, python-format
+msgid "\"%s\" does not exist"
+msgstr "« %s » n’existe pas"
+
+#: config/chroot_local-includes/usr/lib/python3/dist-packages/tails_installer/source.py:66
+#, python-format
+msgid "\"%s\" is not a directory"
+msgstr "« %s » n’est pas un répertoire"
+
+#: config/chroot_local-includes/usr/lib/python3/dist-packages/tails_installer/source.py:77
+#, python-format
+msgid "Skipping \"%(filename)s\""
+msgstr "« %(filename)s » est ignoré"
+
+#: config/chroot_local-includes/usr/lib/python3/dist-packages/tails_installer/utils.py:54
+#, python-format
+msgid ""
+"There was a problem executing `%(cmd)s`.%(out)s\n"
+"%(err)s"
+msgstr "Un problème est survenu lors de l’exécution de `%(cmd)s`.%(out)s\n%(err)s"
+
+#: config/chroot_local-includes/usr/lib/python3/dist-packages/tails_installer/utils.py:126
+msgid "Could not open device for writing."
+msgstr "Impossible d’ouvrir le périphérique en écriture."
+
+#: config/chroot_local-includes/usr/local/bin/keepassxc:17
+#, sh-format
+msgid ""
+"<b><big>Do you want to rename your <i>KeePassXC</i> database?</big></b>\n"
+"\n"
+"You have a <i>KeePassXC</i> database in your <i>Persistent</i> folder:\n"
+"\n"
+"<i>${filename}</i>\n"
+"\n"
+"<i>KeePassXC</i> changed the default name of the database to <i>Passwords.kdbx</i>.\n"
+"\n"
+"Renaming your database to <i>Passwords.kdbx</i> would allow <i>KeePassXC</i> to open it automatically in the future."
+msgstr "<b><big>Voulez-vous renommer votre base de données <i>KeePassXC</i> ?</big></b>\n\nVous avez une base de données <i>KeePassXC</i> dans votre <i>Persistant</i> :\n\n<i>${filename}</i>\n\n<i>KeePassXC</i> a changé le nom par défaut de la base de données en <i>Mots de passe.kdbx</i>.\n\nRenommer votre base de données en <i>Mots de passe.kdbx</i> permettrait à <i>KeePassXC</i> de l’ouvrir automatiquement à l’avenir."
+
+#: config/chroot_local-includes/usr/local/bin/keepassxc:28
+msgid "Rename"
+msgstr "Renommer"
+
+#: config/chroot_local-includes/usr/local/bin/keepassxc:30
+msgid "Keep current name"
+msgstr "Garder le nom actuel"
+
+#: config/chroot_local-includes/usr/src/persistence-setup/lib/Tails/Persistence/Step/Bootstrap.pm:94
+msgid "Persistence wizard - Persistent volume creation"
+msgstr "Assistant de persistance – Création du volume persistant"
+
+#: config/chroot_local-includes/usr/src/persistence-setup/lib/Tails/Persistence/Step/Bootstrap.pm:97
+msgid "Choose a passphrase to protect the persistent volume"
+msgstr "Choisissez une phrase de passe pour protéger le volume persistant"
+
+#: config/chroot_local-includes/usr/src/persistence-setup/lib/Tails/Persistence/Step/Bootstrap.pm:100
+#, perl-brace-format
+msgid ""
+"A {size} persistent volume will be created on the <b>{vendor} {model}</b> "
+"device. Data on this volume will be stored in an encrypted form protected by"
+" a passphrase."
+msgstr "Un volume persistant de {size} sera créé sur le périphérique <b>{vendor} {model}</b>. Les données stockées sur ce périphérique seront chiffrées et protégées par une phrase de passe."
+
+#: config/chroot_local-includes/usr/src/persistence-setup/lib/Tails/Persistence/Step/Bootstrap.pm:105
+msgid "Create"
+msgstr "Créer"
+
+#: config/chroot_local-includes/usr/src/persistence-setup/lib/Tails/Persistence/Step/Bootstrap.pm:148
+msgid ""
+"<b>Beware!</b> Using persistence has consequences that must be well "
+"understood. Tails can't help you if you use it wrong! See the <i>Encrypted "
+"persistence</i> page of the Tails documentation to learn more."
+msgstr "<b>Attention :</b> L’utilisation de la persistance a des conséquences qui doivent être bien comprises. Tails ne peut pas vous aider si vous l’utilisez mal. Consultez la page <i>Persistance chiffrée</i> de la documentation de Tails pour en apprendre davantage."
+
+#: config/chroot_local-includes/usr/src/persistence-setup/lib/Tails/Persistence/Step/Bootstrap.pm:175
+msgid "Passphrase:"
+msgstr "Phrase de passe :"
+
+#: config/chroot_local-includes/usr/src/persistence-setup/lib/Tails/Persistence/Step/Bootstrap.pm:181
+msgid "Verify Passphrase:"
+msgstr "Confirmer la phrase de passe :"
+
+#: config/chroot_local-includes/usr/src/persistence-setup/lib/Tails/Persistence/Step/Bootstrap.pm:191
+#: config/chroot_local-includes/usr/src/persistence-setup/lib/Tails/Persistence/Step/Bootstrap.pm:259
+msgid "Passphrase can't be empty"
+msgstr "La phrase de passe ne peut pas être vide"
+
+#: config/chroot_local-includes/usr/src/persistence-setup/lib/Tails/Persistence/Step/Bootstrap.pm:226
+#: ../config/chroot_local-includes/usr/share/tails/greeter/main.ui.in:326
+msgid "Show Passphrase"
+msgstr "Afficher la phrase de passe"
+
+#: config/chroot_local-includes/usr/src/persistence-setup/lib/Tails/Persistence/Step/Bootstrap.pm:250
+msgid "Passphrases do not match"
+msgstr "Les phrases de passe ne correspondent pas"
+
+#: config/chroot_local-includes/usr/src/persistence-setup/lib/Tails/Persistence/Step/Bootstrap.pm:305
+#: config/chroot_local-includes/usr/src/persistence-setup/lib/Tails/Persistence/Step/Configure.pm:178
+#: config/chroot_local-includes/usr/src/persistence-setup/lib/Tails/Persistence/Step/Delete.pm:101
+msgid "Failed"
+msgstr "Échec"
+
+#: config/chroot_local-includes/usr/src/persistence-setup/lib/Tails/Persistence/Step/Bootstrap.pm:313
+msgid "Mounting Tails persistence partition."
+msgstr "Montage de la partition persistante de Tails."
+
+#: config/chroot_local-includes/usr/src/persistence-setup/lib/Tails/Persistence/Step/Bootstrap.pm:316
+msgid "The Tails persistence partition will be mounted."
+msgstr "La partition persistante de Tails sera montée."
+
+#: config/chroot_local-includes/usr/src/persistence-setup/lib/Tails/Persistence/Step/Bootstrap.pm:325
+msgid "Correcting permissions of the persistent volume."
+msgstr "Correction des droits du volume persistant."
+
+#: config/chroot_local-includes/usr/src/persistence-setup/lib/Tails/Persistence/Step/Bootstrap.pm:328
+msgid "The permissions of the persistent volume will be corrected."
+msgstr "Les droits du volume persistant seront corrigés."
+
+#: config/chroot_local-includes/usr/src/persistence-setup/lib/Tails/Persistence/Step/Bootstrap.pm:336
+msgid "Creating default persistence configuration."
+msgstr "Création de la configuration par défaut de la persistance."
+
+#: config/chroot_local-includes/usr/src/persistence-setup/lib/Tails/Persistence/Step/Bootstrap.pm:339
+msgid "The default persistence configuration will be created."
+msgstr "La configuration par défaut de la persistance sera créée."
+
+#: config/chroot_local-includes/usr/src/persistence-setup/lib/Tails/Persistence/Step/Bootstrap.pm:353
+msgid "Creating..."
+msgstr "Création…"
+
+#: config/chroot_local-includes/usr/src/persistence-setup/lib/Tails/Persistence/Step/Bootstrap.pm:355
+msgid "Creating the persistent volume..."
+msgstr "Création du volume persistant…"
+
+#: config/chroot_local-includes/usr/src/persistence-setup/lib/Tails/Persistence/Step/Configure.pm:86
+msgid "Persistence wizard - Persistent volume configuration"
+msgstr "Assistant de persistance – Configuration du volume persistant"
+
+#: config/chroot_local-includes/usr/src/persistence-setup/lib/Tails/Persistence/Step/Configure.pm:89
+msgid "Specify the files that will be saved in the persistent volume"
+msgstr "Indiquez les fichiers à enregistrer dans le volume persistant"
+
+#: config/chroot_local-includes/usr/src/persistence-setup/lib/Tails/Persistence/Step/Configure.pm:92
+#, perl-brace-format
+msgid ""
+"The selected files will be stored in the encrypted partition {partition} "
+"({size}), on the <b>{vendor} {model}</b> device."
+msgstr "Les fichiers sélectionnés seront stockés dans la partition chiffrée {partition} ({size}) sur le périphérique <b>{vendor} {model}</b>."
+
+#: config/chroot_local-includes/usr/src/persistence-setup/lib/Tails/Persistence/Step/Configure.pm:98
+msgid "Save"
+msgstr "Enregistrer"
+
+#: config/chroot_local-includes/usr/src/persistence-setup/lib/Tails/Persistence/Step/Configure.pm:191
+msgid "Saving..."
+msgstr "Enregistrement…"
+
+#: config/chroot_local-includes/usr/src/persistence-setup/lib/Tails/Persistence/Step/Configure.pm:193
+msgid "Saving persistence configuration..."
+msgstr "Enregistrement de la configuration de la persistance…"
+
+#: config/chroot_local-includes/usr/src/persistence-setup/lib/Tails/Persistence/Step/Delete.pm:51
+msgid "Persistence wizard - Persistent volume deletion"
+msgstr "Assistant de persistance – Suppression du volume persistant"
+
+#: config/chroot_local-includes/usr/src/persistence-setup/lib/Tails/Persistence/Step/Delete.pm:54
+msgid "Your persistent data will be deleted."
+msgstr "Vos données persistantes seront supprimées."
+
+#: config/chroot_local-includes/usr/src/persistence-setup/lib/Tails/Persistence/Step/Delete.pm:58
+#, perl-brace-format
+msgid ""
+"The persistent volume {partition} ({size}), on the <b>{vendor} {model}</b> "
+"device, will be deleted."
+msgstr "Le volume persistant {partition} ({size}) du périphérique <b>{vendor} {model}</b> sera supprimé."
+
+#: config/chroot_local-includes/usr/src/persistence-setup/lib/Tails/Persistence/Step/Delete.pm:64
+msgid "Delete"
+msgstr "Supprimer"
+
+#: config/chroot_local-includes/usr/src/persistence-setup/lib/Tails/Persistence/Step/Delete.pm:114
+msgid "Deleting..."
+msgstr "Suppression…"
+
+#: config/chroot_local-includes/usr/src/persistence-setup/lib/Tails/Persistence/Step/Delete.pm:116
+msgid "Deleting the persistent volume..."
+msgstr "Suppression du volume persistant…"
+
+#: config/chroot_local-includes/usr/src/persistence-setup/lib/Tails/Persistence/Configuration/Presets.pm:53
+msgid "Personal Data"
+msgstr "Données personnelles"
+
+#: config/chroot_local-includes/usr/src/persistence-setup/lib/Tails/Persistence/Configuration/Presets.pm:55
+msgid "Keep files stored in the `Persistent' directory"
+msgstr "Conserver les fichiers stockés dans le répertoire `Persistant’"
+
+#: config/chroot_local-includes/usr/src/persistence-setup/lib/Tails/Persistence/Configuration/Presets.pm:68
+msgid "Welcome Screen"
+msgstr "Écran de bienvenue"
+
+#: config/chroot_local-includes/usr/src/persistence-setup/lib/Tails/Persistence/Configuration/Presets.pm:70
+msgid "Language, administration password, and additional settings"
+msgstr "Langue, mot de passe d’administration et paramètres supplémentaires"
+
+#: config/chroot_local-includes/usr/src/persistence-setup/lib/Tails/Persistence/Configuration/Presets.pm:83
+msgid "Browser Bookmarks"
+msgstr "Marque-pages du navigateur"
+
+#: config/chroot_local-includes/usr/src/persistence-setup/lib/Tails/Persistence/Configuration/Presets.pm:85
+msgid "Bookmarks saved in the Tor Browser"
+msgstr "Marque-pages enregistrés dans le Navigateur Tor"
+
+#: config/chroot_local-includes/usr/src/persistence-setup/lib/Tails/Persistence/Configuration/Presets.pm:98
+msgid "Network Connections"
+msgstr "Connexions réseau"
+
+#: config/chroot_local-includes/usr/src/persistence-setup/lib/Tails/Persistence/Configuration/Presets.pm:100
+msgid "Configuration of network devices and connections"
+msgstr "Configuration des périphériques du réseau et connexions"
+
+#: config/chroot_local-includes/usr/src/persistence-setup/lib/Tails/Persistence/Configuration/Presets.pm:115
+msgid "Software installed when starting Tails"
+msgstr "Logiciels installés lors du démarrage de Tails"
+
+#: config/chroot_local-includes/usr/src/persistence-setup/lib/Tails/Persistence/Configuration/Presets.pm:133
+msgid "Printers"
+msgstr "Imprimantes"
+
+#: config/chroot_local-includes/usr/src/persistence-setup/lib/Tails/Persistence/Configuration/Presets.pm:135
+msgid "Printers configuration"
+msgstr "Configuration des imprimantes"
+
+#: config/chroot_local-includes/usr/src/persistence-setup/lib/Tails/Persistence/Configuration/Presets.pm:148
+msgid "Thunderbird"
+msgstr "Thunderbird"
+
+#: config/chroot_local-includes/usr/src/persistence-setup/lib/Tails/Persistence/Configuration/Presets.pm:150
+msgid "Thunderbird emails, feeds, and OpenPGP keys"
+msgstr "Courriels, flux de Thunderbird et clés OpenPGP"
+
+#: config/chroot_local-includes/usr/src/persistence-setup/lib/Tails/Persistence/Configuration/Presets.pm:163
+msgid "GnuPG"
+msgstr "GnuPG"
+
+#: config/chroot_local-includes/usr/src/persistence-setup/lib/Tails/Persistence/Configuration/Presets.pm:165
+msgid "OpenPGP keys outside of Thunderbird"
+msgstr "Clés OpenPGP en dehors de Thunderbird"
+
+#: config/chroot_local-includes/usr/src/persistence-setup/lib/Tails/Persistence/Configuration/Presets.pm:178
+msgid "Bitcoin Client"
+msgstr "Client Bitcoin"
+
+#: config/chroot_local-includes/usr/src/persistence-setup/lib/Tails/Persistence/Configuration/Presets.pm:180
+msgid "Electrum's bitcoin wallet and configuration"
+msgstr "Porte-monnaie Bitcoin et configuration d’Electrum"
+
+#: config/chroot_local-includes/usr/src/persistence-setup/lib/Tails/Persistence/Configuration/Presets.pm:193
+msgid "Pidgin"
+msgstr "Pidgin"
+
+#: config/chroot_local-includes/usr/src/persistence-setup/lib/Tails/Persistence/Configuration/Presets.pm:195
+msgid "Pidgin profiles and OTR keyring"
+msgstr "Profils Pidgin et trousseau OTR"
+
+#: config/chroot_local-includes/usr/src/persistence-setup/lib/Tails/Persistence/Configuration/Presets.pm:208
+msgid "SSH Client"
+msgstr "Client SSH"
+
+#: config/chroot_local-includes/usr/src/persistence-setup/lib/Tails/Persistence/Configuration/Presets.pm:210
+msgid "SSH keys, configuration and known hosts"
+msgstr "Clés, configuration et hôtes connus SSH"
+
+#: config/chroot_local-includes/usr/src/persistence-setup/lib/Tails/Persistence/Configuration/Presets.pm:223
+msgid "Dotfiles"
+msgstr "Dotfiles"
+
+#: config/chroot_local-includes/usr/src/persistence-setup/lib/Tails/Persistence/Configuration/Presets.pm:225
+msgid "Symlink every file in the Dotfiles folder into the Home folder"
+msgstr "Pour chaque fichier qui se trouve dans le dossier Dotfiles, créer un lien dans le dossier personnel « home »"
+
+#: config/chroot_local-includes/usr/src/persistence-setup/lib/Tails/Persistence/Configuration/Setting.pm:111
+msgid "Custom"
+msgstr "Personnalisé"
+
+#: config/chroot_local-includes/usr/src/persistence-setup/lib/Tails/Persistence/Setup.pm:285
+msgid "Setup Tails persistent volume"
+msgstr "Configurer le volume persistant de Tails"
+
+#: config/chroot_local-includes/usr/src/persistence-setup/lib/Tails/Persistence/Setup.pm:364
+#: config/chroot_local-includes/usr/src/persistence-setup/lib/Tails/Persistence/Setup.pm:491
+#: config/chroot_local-includes/usr/src/perl5lib/lib/Tails/RunningSystem.pm:221
+#: config/chroot_local-includes/usr/local/bin/tails-upgrade-frontend-wrapper:77
+#: config/chroot_local-includes/usr/local/sbin/unsafe-browser:29
+#: ../config/chroot_local-includes/usr/share/tails/tca/main.ui.in:313
+#: ../config/chroot_local-includes/usr/share/tails/tca/main.ui.in:668
+msgid "Error"
+msgstr "Erreur"
+
+#: config/chroot_local-includes/usr/src/persistence-setup/lib/Tails/Persistence/Setup.pm:390
+msgid "Device already has a persistent volume."
+msgstr "Le périphérique comprend déjà un volume persistant."
+
+#: config/chroot_local-includes/usr/src/persistence-setup/lib/Tails/Persistence/Setup.pm:397
+msgid "Device has not enough unallocated space."
+msgstr "Le périphérique n’a pas assez d’espace non alloué."
+
+#: config/chroot_local-includes/usr/src/persistence-setup/lib/Tails/Persistence/Setup.pm:403
+#: config/chroot_local-includes/usr/src/persistence-setup/lib/Tails/Persistence/Setup.pm:416
+msgid "Device has no persistent volume."
+msgstr "Le périphérique n’a pas de volume persistant."
+
+#: config/chroot_local-includes/usr/src/persistence-setup/lib/Tails/Persistence/Setup.pm:409
+msgid ""
+"Cannot delete the persistent volume while in use. You should restart Tails "
+"without persistence."
+msgstr "Impossible de supprimer le volume persistant pendant qu’il est utilisé. Vous devriez redémarrer Tails sans persistance."
+
+#: config/chroot_local-includes/usr/src/persistence-setup/lib/Tails/Persistence/Setup.pm:421
+msgid "Persistence volume is not unlocked."
+msgstr "Le volume persistant n’est pas déverrouillé."
+
+#: config/chroot_local-includes/usr/src/persistence-setup/lib/Tails/Persistence/Setup.pm:425
+msgid "Persistence volume is not mounted."
+msgstr "Le volume persistant n’est pas monté."
+
+#: config/chroot_local-includes/usr/src/persistence-setup/lib/Tails/Persistence/Setup.pm:430
+msgid "Persistence volume is not readable. Permissions or ownership problems?"
+msgstr "Le volume persistant n’est pas accessible en lecture. Problèmes de droits ou de propriété ?"
+
+#: config/chroot_local-includes/usr/src/persistence-setup/lib/Tails/Persistence/Setup.pm:435
+msgid "Persistence volume is not writable."
+msgstr "Le volume persistant n’est pas accessible en écriture."
+
+#: config/chroot_local-includes/usr/src/persistence-setup/lib/Tails/Persistence/Setup.pm:444
+msgid "Tails is running from non-USB / non-SDIO device."
+msgstr "Tails s’exécute à partir d’un périphérique non USB, non SDIO."
+
+#: config/chroot_local-includes/usr/src/persistence-setup/lib/Tails/Persistence/Setup.pm:449
+msgid "Device is optical."
+msgstr "Le périphérique est optique."
+
+#: config/chroot_local-includes/usr/src/persistence-setup/lib/Tails/Persistence/Setup.pm:456
+msgid "Device was not created using a USB image or Tails Installer."
+msgstr "Le périphérique n’a pas été créé en utilisant une image USB ou le programme d’installation de Tails."
+
+#: config/chroot_local-includes/usr/src/persistence-setup/lib/Tails/Persistence/Setup.pm:698
+msgid "Persistence wizard - Finished"
+msgstr "Assistant de persistance – Terminé"
+
+#: config/chroot_local-includes/usr/src/persistence-setup/lib/Tails/Persistence/Setup.pm:701
+msgid ""
+"Any changes you have made will only take effect after restarting Tails."
+msgstr "Toute modification que vous avez effectuée ne prendra effet qu’après le redémarrage de Tails."
+
+#: config/chroot_local-includes/usr/src/persistence-setup/lib/Tails/Persistence/Setup.pm:711
+msgid "Restart Now"
+msgstr "Redémarrer maintenant"
+
+#: config/chroot_local-includes/usr/local/bin/replace-su-with-sudo:19
+msgid "su is disabled. Please use sudo instead."
+msgstr "su est désactivée. Veuillez plutôt utiliser sudo."
+
+#: config/chroot_local-includes/usr/src/perl5lib/lib/Tails/RunningSystem.pm:223
+msgid ""
+"The device Tails is running from cannot be found. Maybe you used the 'toram'"
+" option?"
+msgstr "Le périphérique sur lequel Tails tourne ne peut pas être trouvé. Peut-être avez-vous utilisé l’option « toram » ?"
+
+#: config/chroot_local-includes/usr/src/perl5lib/lib/Tails/RunningSystem.pm:251
+msgid ""
+"The drive Tails is running from cannot be found. Maybe you used the 'toram' "
+"option?"
+msgstr "Le périphérique sur lequel Tails tourne ne peut pas être trouvé. Peut-être avez-vous utilisée l’option « toram » ?"
+
+#: config/chroot_local-includes/usr/local/lib/seahorse-tool-wrapper:42
+msgid "Import Failed"
+msgstr "Échec d’importation"
+
+#. Translators: Don't translate {path} or {error},
+#. they are placeholders and will be replaced.
+#. They need to be present in the translated string.
+#: config/chroot_local-includes/usr/local/lib/seahorse-tool-wrapper:46
+#, python-brace-format
+msgid ""
+"Failed to import keys from {path}:\n"
+"{error}"
+msgstr "Échec d’importation des clés de {path} :\n{error}"
+
+#: config/chroot_local-includes/usr/local/lib/seahorse-tool-wrapper:54
+msgid "Key Imported"
+msgid_plural "Keys Imported"
+msgstr[0] "La clé a été importée"
+msgstr[1] "Les clés ont été importées"
+
+#. Translators: Don't translate {uids}, it's a placeholder and
+#. will be replaced. It needs to be present in the translated string.
+#: config/chroot_local-includes/usr/local/lib/seahorse-tool-wrapper:57
+#, python-brace-format
+msgid "Imported a key for {uids}"
+msgid_plural "Imported keys for {uids}"
+msgstr[0] "Importer une clé pour {uids}"
+msgstr[1] "Importer des clés pour {uids}"
+
+#: config/chroot_local-includes/usr/share/gnome-shell/extensions/status-menu-helper@tails.boum.org/extension.js:75
+msgid "Lock screen"
+msgstr "Verrouillage de l’écran"
+
+#: config/chroot_local-includes/usr/share/gnome-shell/extensions/status-menu-helper@tails.boum.org/extension.js:79
+msgid "Suspend"
+msgstr "Interrompre"
+
+#: config/chroot_local-includes/usr/share/gnome-shell/extensions/status-menu-helper@tails.boum.org/extension.js:83
+msgid "Restart"
+msgstr "Redémarrer"
+
+#: config/chroot_local-includes/usr/share/gnome-shell/extensions/status-menu-helper@tails.boum.org/extension.js:87
+msgid "Power Off"
+msgstr "Éteindre"
+
+#: config/chroot_local-includes/usr/local/bin/tails-about:22
+#: ../config/chroot_local-includes/usr/share/desktop-directories/Tails.directory.in.h:1
+msgid "Tails"
+msgstr "Tails"
+
+#: config/chroot_local-includes/usr/local/bin/tails-about:25
+#: ../config/chroot_local-includes/usr/share/applications/tails-about.desktop.in.h:1
+msgid "About Tails"
+msgstr "À propos de Tails"
+
+#: config/chroot_local-includes/usr/local/bin/tails-about:35
+msgid "The Amnesic Incognito Live System"
+msgstr "The Amnesic Incognito Live System"
+
+#: config/chroot_local-includes/usr/local/bin/tails-about:36
+#, python-format
+msgid ""
+"Build information:\n"
+"%s"
+msgstr "Renseignements de compilation :\n%s"
+
+#: config/chroot_local-includes/usr/local/bin/tails-about:54
+msgid "not available"
+msgstr "non disponible"
+
+#. Translators: Don't translate {details}, it's a placeholder and will
+#. be replaced.
+#: config/chroot_local-includes/usr/local/sbin/tails-additional-software:148
+#, python-brace-format
+msgid ""
+"{details} Please check your list of additional software or read the system "
+"log to understand the problem."
+msgstr "{details} Veuillez vérifier votre liste de logiciels supplémentaires ou lire le journal système afin de mieux comprendre le problème."
+
+#: config/chroot_local-includes/usr/local/sbin/tails-additional-software:153
+msgid ""
+"Please check your list of additional software or read the system log to "
+"understand the problem."
+msgstr "Veuillez vérifier votre liste de logiciels supplémentaires ou lire le journal système afin de mieux comprendre le problème."
+
+#: config/chroot_local-includes/usr/local/sbin/tails-additional-software:157
+msgid "Show Log"
+msgstr "Afficher le journal"
+
+#: config/chroot_local-includes/usr/local/sbin/tails-additional-software:157
+msgid "Configure"
+msgstr "Configurer"
+
+#. Translators: Don't translate {beginning} or {last}, they are
+#. placeholders and will be replaced.
+#: config/chroot_local-includes/usr/local/sbin/tails-additional-software:223
+#, python-brace-format
+msgid "{beginning} and {last}"
+msgstr "{beginning} et {last}"
+
+#: config/chroot_local-includes/usr/local/sbin/tails-additional-software:224
+msgid ", "
+msgstr ", "
+
+#. Translators: Don't translate {packages}, it's a placeholder and will
+#. be replaced.
+#: config/chroot_local-includes/usr/local/sbin/tails-additional-software:290
+#: config/chroot_local-includes/usr/local/sbin/tails-additional-software:320
+#, python-brace-format
+msgid "Add {packages} to your additional software?"
+msgstr "Ajouter {packages} à vos logiciels supplémentaires ?"
+
+#: config/chroot_local-includes/usr/local/sbin/tails-additional-software:292
+msgid ""
+"To install it automatically from your persistent storage when starting "
+"Tails."
+msgstr "Pour l’installer automatiquement à partir de votre stockage persistant lors du démarrage de Tails."
+
+#: config/chroot_local-includes/usr/local/sbin/tails-additional-software:294
+msgid "Install Every Time"
+msgstr "Installer à chaque fois"
+
+#: config/chroot_local-includes/usr/local/sbin/tails-additional-software:295
+#: config/chroot_local-includes/usr/local/sbin/tails-additional-software:326
+msgid "Install Only Once"
+msgstr "Installer une seule fois"
+
+#: config/chroot_local-includes/usr/local/sbin/tails-additional-software:301
+#: config/chroot_local-includes/usr/local/sbin/tails-additional-software:331
+#: config/chroot_local-includes/usr/local/sbin/tails-additional-software:371
+msgid "The configuration of your additional software failed."
+msgstr "La configuration de vos logiciels supplémentaires a échoué."
+
+#: config/chroot_local-includes/usr/local/sbin/tails-additional-software:322
+msgid ""
+"To install it automatically when starting Tails, you can create a persistent"
+" storage and activate the <b>Additional Software</b> feature."
+msgstr "Pour l’installer automatiquement lors du démarrage de Tails, vous pouvez créer un stockage persistant et activer l’option <b>Logiciels supplémentaires</b>."
+
+#: config/chroot_local-includes/usr/local/sbin/tails-additional-software:325
+msgid "Create Persistent Storage"
+msgstr "Créer un stockage persistant"
+
+#: config/chroot_local-includes/usr/local/sbin/tails-additional-software:333
+msgid "Creating your persistent storage failed."
+msgstr "La création de votre stockage persistant a échoué."
+
+#. Translators: Don't translate {packages}, it's a placeholder and
+#. will be replaced.
+#: config/chroot_local-includes/usr/local/sbin/tails-additional-software:342
+#, python-brace-format
+msgid "You could install {packages} automatically when starting Tails"
+msgstr "Vous pourriez installer {packages} automatiquement lors du démarrage de Tails"
+
+#: config/chroot_local-includes/usr/local/sbin/tails-additional-software:345
+msgid "To do so, you need to run Tails from a USB stick."
+msgstr "Pour ce faire, vous devez lancer Tails à partir d’une clé USB."
+
+#. Translators: Don't translate {packages}, it's a placeholder and will be
+#. replaced.
+#: config/chroot_local-includes/usr/local/sbin/tails-additional-software:359
+#, python-brace-format
+msgid "Remove {packages} from your additional software?"
+msgstr "Enlever {packages} de vos logiciels supplémentaires ?"
+
+#. Translators: Don't translate {packages}, it's a placeholder
+#. and will be replaced.
+#: config/chroot_local-includes/usr/local/sbin/tails-additional-software:363
+#, python-brace-format
+msgid "This will stop installing {packages} automatically."
+msgstr "Cela arrêtera l’installation automatique de {packages}."
+
+#: config/chroot_local-includes/usr/local/sbin/tails-additional-software:365
+#: config/chroot_local-includes/usr/local/bin/tails-additional-software-config:154
+msgid "Remove"
+msgstr "Supprimer"
+
+#: config/chroot_local-includes/usr/local/sbin/tails-additional-software:544
+msgid "Installing your additional software from persistent storage..."
+msgstr "Installation de vos logiciels supplémentaires à partir du stockage persistant…"
+
+#: config/chroot_local-includes/usr/local/sbin/tails-additional-software:546
+msgid "This can take several minutes."
+msgstr "Cela peut prendre plusieurs minutes."
+
+#: config/chroot_local-includes/usr/local/sbin/tails-additional-software:559
+msgid "The installation of your additional software failed"
+msgstr "L’installation de vos logiciels supplémentaires a échoué"
+
+#: config/chroot_local-includes/usr/local/sbin/tails-additional-software:574
+msgid "Additional software installed successfully"
+msgstr "Logiciels supplémentaires installés avec succès"
+
+#: config/chroot_local-includes/usr/local/sbin/tails-additional-software:594
+msgid "The check for upgrades of your additional software failed"
+msgstr "La vérification de la présence de mises à niveau pour vos logiciels supplémentaires a échoué"
+
+#: config/chroot_local-includes/usr/local/sbin/tails-additional-software:596
+#: config/chroot_local-includes/usr/local/sbin/tails-additional-software:604
+msgid ""
+"Please check your network connection, restart Tails, or read the system log "
+"to understand the problem."
+msgstr "Veuillez vérifier votre connexion réseau, essayer de redémarrer Tails, ou lire le journal système afin de mieux comprendre le problème."
+
+#: config/chroot_local-includes/usr/local/sbin/tails-additional-software:603
+msgid "The upgrade of your additional software failed"
+msgstr "La mise à niveau de vos logiciels supplémentaires a échoué"
+
+#: config/chroot_local-includes/usr/local/lib/tails-additional-software-notify:37
+msgid "Documentation"
+msgstr "Documentation"
+
+#. Translators: Don't translate {package}, it's a placeholder and will be
+#. replaced.
+#: config/chroot_local-includes/usr/local/bin/tails-additional-software-config:94
+#, python-brace-format
+msgid ""
+"Remove {package} from your additional software? This will stop installing "
+"the package automatically."
+msgstr "Enlever {package} de vos logiciels supplémentaires ? Cela arrêtera l’installation automatique du paquet."
+
+#. Translators: Don't translate {pkg}, it's a placeholder and will be
+#. replaced.
+#: config/chroot_local-includes/usr/local/bin/tails-additional-software-config:105
+#, python-brace-format
+msgid "Failed to remove {pkg}"
+msgstr "Échec de la suppression de {pkg}"
+
+#: config/chroot_local-includes/usr/local/bin/tails-additional-software-config:122
+msgid "Failed to read additional software configuration"
+msgstr "Échec de la lecture de la configuration des logiciels supplémentaires"
+
+#. Translators: Don't translate {package}, it's a placeholder and will be
+#. replaced.
+#: config/chroot_local-includes/usr/local/bin/tails-additional-software-config:152
+#, python-brace-format
+msgid "Stop installing {package} automatically"
+msgstr "Arrêter d’installer {package} automatiquement"
+
+#: config/chroot_local-includes/usr/local/bin/tails-additional-software-config:178
+msgid ""
+"To do so, install some software using <a href=\"synaptic.desktop\">Synaptic "
+"Package Manager</a> or <a href=\"org.gnome.Terminal.desktop\">APT on the "
+"command line</a>."
+msgstr "Pour ce faire, installez des logiciels en utilisant le <a href=\"synaptic.desktop\">gestionnaire de paquets Synaptic</a> ou <a href=\"org.gnome.Terminal.desktop\">APT en ligne de commande</a>."
+
+#: config/chroot_local-includes/usr/local/bin/tails-additional-software-config:187
+msgid ""
+"To do so, unlock your persistent storage when starting Tails and install "
+"some software using <a href=\"synaptic.desktop\">Synaptic Package "
+"Manager</a> or <a href=\"org.gnome.Terminal.desktop\">APT on the command "
+"line</a>."
+msgstr "Pour ce faire, déverrouillez votre stockage persistant lors du démarrage de Tails et installez des logiciels en utilisant le <a href=\"synaptic.desktop\">gestionnaire de paquets Synaptic</a> ou <a href=\"org.gnome.Terminal.desktop\">APT en ligne de commande</a>."
+
+#: config/chroot_local-includes/usr/local/bin/tails-additional-software-config:197
+msgid ""
+"To do so, create a persistent storage and install some software using <a "
+"href=\"synaptic.desktop\">Synaptic Package Manager</a> or <a "
+"href=\"org.gnome.Terminal.desktop\">APT on the command line</a>."
+msgstr "Pour ce faire, créez un stockage persistant et installez des logiciels en utilisant le <a href=\"synaptic.desktop\">gestionnaire de paquets Synaptic</a> ou <a href=\"org.gnome.Terminal.desktop\">APT en ligne de commande</a>."
+
+#: config/chroot_local-includes/usr/local/bin/tails-additional-software-config:205
+msgid ""
+"To do so, install Tails on a USB stick and create a persistent storage."
+msgstr "Pour ce faire, installez Tails sur une clé USB et créez un espace de stockage persistant."
+
+#: config/chroot_local-includes/usr/local/bin/tails-additional-software-config:251
+msgid "[package not available]"
+msgstr "[paquet non disponible]"
+
+#: config/chroot_local-includes/usr/local/lib/tails-htp-notify-user:68
+msgid "Failed to synchronize the clock!"
+msgstr "Échec de synchronisation de l’horloge"
+
+#: config/chroot_local-includes/usr/local/bin/tails-screen-locker:110
+msgid "Lock Screen"
+msgstr "Verrouiller l’écran"
+
+#: config/chroot_local-includes/usr/local/bin/tails-screen-locker:125
+msgid "Screen Locker"
+msgstr "Verrouillage de l’écran"
+
+#: config/chroot_local-includes/usr/local/bin/tails-screen-locker:131
+msgid "Set up a password to unlock the screen."
+msgstr "Définir un mot de passe pour déverrouiller l’écran."
+
+#: config/chroot_local-includes/usr/local/bin/tails-screen-locker:149
+#: ../config/chroot_local-includes/usr/share/tails/tca/main.ui.in:1761
+msgid "Password"
+msgstr "Mot de passe"
+
+#: config/chroot_local-includes/usr/local/bin/tails-screen-locker:150
+#: ../config/chroot_local-includes/usr/share/tails/greeter/additional_settings.ui.in:93
+msgid "Confirm"
+msgstr "Confirmer"
+
+#: config/chroot_local-includes/usr/local/bin/tails-security-check:121
+msgid "This version of Tails has known security issues:"
+msgstr "Cette version de Tails a des problèmes de sécurité connus :"
+
+#: config/chroot_local-includes/usr/local/bin/tails-security-check:132
+msgid "Known security issues"
+msgstr "Problèmes de sécurité connus"
+
+#: config/chroot_local-includes/usr/local/lib/tails-spoof-mac:56
+#, sh-format
+msgid "Network card ${nic} disabled"
+msgstr "La carte réseau ${nic} est désactivée"
+
+#: config/chroot_local-includes/usr/local/lib/tails-spoof-mac:57
+#, sh-format
+msgid ""
+"MAC address anonymization failed for network card ${nic_name} (${nic}) so it is temporarily disabled.\n"
+"You might prefer to restart Tails and disable MAC address anonymization."
+msgstr "L’anonymisation de l’adresse MAC a échoué pour la carte réseau ${nic_name} (${nic}) ; elle est donc temporairement désactivée.\nVous préférerez peut-être redémarrer Tails et désactiver l’anonymisation de l’adresse MAC."
+
+#: config/chroot_local-includes/usr/local/lib/tails-spoof-mac:66
+msgid "All networking disabled"
+msgstr "La mise en réseau est désactivée"
+
+#: config/chroot_local-includes/usr/local/lib/tails-spoof-mac:67
+#, sh-format
+msgid ""
+"MAC address anonymization failed for network card ${nic_name} (${nic}). The error recovery also failed so all networking is disabled.\n"
+"You might prefer to restart Tails and disable MAC address anonymization."
+msgstr "L’anonymisation de l’adresse MAC a échoué pour la carte réseau ${nic_name} (${nic}). Le dépannage de cette erreur a également échoué et toutes les fonctions de réseau sont donc désactivées.\nVous préférerez peut-être redémarrer Tails et désactiver l’anonymisation de l’adresse MAC."
+
+#: config/chroot_local-includes/usr/local/bin/tails-upgrade-frontend-wrapper:36
+#, python-brace-format
+msgid ""
+"<b>Not enough memory available to check for upgrades.</b>\n"
+"\n"
+"Make sure this system satisfies the requirements for running Tails.\n"
+"See file:///usr/share/doc/tails/website/doc/about/requirements.en.html\n"
+"\n"
+"Try to restart Tails to check for upgrades again.\n"
+"\n"
+"Or do a manual upgrade.\n"
+"See {manual_upgrade_url}"
+msgstr "<b>Il n’y a pas assez de mémoire libre pour vérifier la présence de mises à niveau.</b>\n\nAssurez-vous que ce système répond aux exigences d’exécution de Tails.\nConsultez file:///usr/share/doc/tails/website/doc/about/requirements.fr.html\n\nEssayez de redémarrer Tails pour revérifier la présence de mises à niveau.\n\nOu effectuez une mise à niveau manuelle.\nConsultez {manual_upgrade_url}"
+
+#: config/chroot_local-includes/usr/local/bin/tails-upgrade-frontend-wrapper:76
+#: config/chroot_local-includes/usr/local/sbin/unsafe-browser:28
+msgid "error:"
+msgstr "erreur :"
+
+#: config/chroot_local-includes/usr/local/lib/tails-virt-notify-user:23
+msgid "Warning: virtual machine detected!"
+msgstr "Avertissement : Une machine virtuelle a été détectée"
+
+#: config/chroot_local-includes/usr/local/lib/tails-virt-notify-user:25
+msgid "Warning: non-free virtual machine detected!"
+msgstr "Avertissement : Une machine virtuelle non libre a été détectée"
+
+#: config/chroot_local-includes/usr/local/lib/tails-virt-notify-user:27
+msgid ""
+"Both the host operating system and the virtualization software are able to "
+"monitor what you are doing in Tails. Only free software can be considered "
+"trustworthy, for both the host operating system and the virtualization "
+"software."
+msgstr "Le système d’exploitation hôte et le logiciel de virtualisation peuvent tous deux surveiller ce que vous faites dans Tails. Seuls les logiciels libres peuvent être considérés de confiance, à la fois pour le système d’exploitation hôte et le logiciel de virtualisation."
+
+#: config/chroot_local-includes/usr/local/lib/tails-virt-notify-user:40
+msgid "Don't Show Again"
+msgstr "Ne plus afficher"
+
+#: config/chroot_local-includes/usr/local/lib/tails-virt-notify-user:42
+msgid "Learn More"
+msgstr "En apprendre davantage"
+
+#: config/chroot_local-includes/usr/lib/python3/dist-packages/tca/config.py:8
+#: ../config/chroot_local-includes/usr/share/applications/tca.desktop.in.h:1
+msgid "Tor Connection"
+msgstr "Connexion à Tor"
+
+#: config/chroot_local-includes/usr/lib/python3/dist-packages/tca/ui/main_window.py:203
+#: config/chroot_local-includes/usr/lib/python3/dist-packages/tca/ui/main_window.py:495
+#, python-brace-format
+msgid "Invalid: {exception}"
+msgstr "Invalide : {exception}"
+
+#: config/chroot_local-includes/usr/lib/python3/dist-packages/tca/ui/main_window.py:215
+#: config/chroot_local-includes/usr/lib/python3/dist-packages/tca/ui/main_window.py:508
+msgid "You need to configure an obfs4 bridge to hide that you are using Tor"
+msgstr "Vous devez utiliser un pont obfs4 pour dissimuler le fait que vous utilisez Tor"
+
+#: config/chroot_local-includes/usr/lib/python3/dist-packages/tca/ui/main_window.py:308
+msgid "Connecting to Tor without bridges…"
+msgstr "Connexion à Tor sans pont…"
+
+#: config/chroot_local-includes/usr/lib/python3/dist-packages/tca/ui/main_window.py:315
+#: config/chroot_local-includes/usr/lib/python3/dist-packages/tca/ui/main_window.py:339
+msgid "Connecting to Tor with default bridges…"
+msgstr "Connexion à Tor avec les ponts par défaut…"
+
+#: config/chroot_local-includes/usr/lib/python3/dist-packages/tca/ui/main_window.py:322
+msgid "Connecting to Tor with custom bridges…"
+msgstr "Connexion à Tor avec des ponts personnalisés…"
+
+#: config/chroot_local-includes/usr/lib/python3/dist-packages/tca/ui/main_window.py:414
+msgid ""
+"Connected to Tor successfully!\n"
+"\n"
+"You can now browse the Internet anonymously and uncensored."
+msgstr "Vous êtes connecté à Tor avec succès.\n\nVous pouvez maintenant parcourir Internet anonymement et sans censure."
+
+#: config/chroot_local-includes/usr/lib/python3/dist-packages/tca/ui/main_window.py:498
+msgid "Bridge address malformed"
+msgstr "L’adresse du pont est malformée"
+
+#: config/chroot_local-includes/usr/lib/python3/dist-packages/tca/ui/main_window.py:514
+msgid "Setting a bridge is needed if you want to hide that you are using Tor"
+msgstr "Vous devez définir un pont si vous voulez dissimuler le fait que vous utilisez Tor."
+
+#: config/chroot_local-includes/usr/lib/python3/dist-packages/tca/ui/main_window.py:777
+msgid "Are you sure you want to lose progress?"
+msgstr "Voulez-vous vraiment perdre la progression ?"
+
+#: config/chroot_local-includes/usr/lib/python3/dist-packages/tca/ui/main_window.py:781
+msgid ""
+"Tails will continue connecting to Tor after you close the Tor Connection assistant.\n"
+"\n"
+"If connecting to Tor fails, you will have to wait again until the end of the progress bar to be able to troubleshoot your connection."
+msgstr "Tails sera encore connecté à Tor une fois que vous aurez fermé l’assistant de connexion à Tor.\n\nSi la connexion à Tor échoue, vous devrez de nouveau attendre la fin de la barre de progression afin de dépanner votre connexion."
+
+#: config/chroot_local-includes/usr/local/bin/thunderbird:41
+msgid "You need to migrate your OpenPGP keys"
+msgstr "Vous devez migrer vos clés OpenPGP"
+
+#: config/chroot_local-includes/usr/local/bin/thunderbird:43
+msgid ""
+"<i>Thunderbird</i> 78 now replaces the <i>Enigmail</i> extension with built-"
+"in support for OpenPGP encryption. To continue using your OpenPGP keys in "
+"<i>Thunderbird</i>, follow our migration instructions."
+msgstr "<i>Thunderbird</i> 78 remplace désormais l’extension <i>Enigmail</i> par une prise en charge intégrée du chiffrement OpenPGP. Afin de continuer à utiliser vos clés OpenPGP dans <i>Thunderbird</i>, veuillez suivre nos instructions de migration."
+
+#: config/chroot_local-includes/usr/local/bin/thunderbird:45
+msgid "_Open Migration Instructions"
+msgstr "_Ouvrir les instructions de migration"
+
+#: config/chroot_local-includes/usr/local/bin/thunderbird:46
+msgid "_Migrate Later"
+msgstr "_Migrer ultérieurement"
+
+#: config/chroot_local-includes/usr/bin/tor-browser:48
+msgid "Tor is not ready"
+msgstr "Tor n’est pas prêt"
+
+#: config/chroot_local-includes/usr/bin/tor-browser:49
+msgid "Tor is not ready. Start Tor Browser anyway?"
+msgstr "Tor n’est pas prêt. Démarrer le navigateur Tor quand même ?"
+
+#: config/chroot_local-includes/usr/bin/tor-browser:50
+#: ../config/chroot_local-includes/usr/share/tails/tca/main.ui.in:1559
+msgid "Start Tor Browser"
+msgstr "Démarrer le Navigateur Tor"
+
+#: config/chroot_local-includes/usr/share/gnome-shell/extensions/torstatus@tails.boum.org/extension.js:35
+msgid "Tor Status"
+msgstr "État de Tor"
+
+#: config/chroot_local-includes/usr/share/gnome-shell/extensions/torstatus@tails.boum.org/extension.js:50
+msgid "Open Onion Circuits"
+msgstr "Ouvrir Circuits oignon"
+
+#. Translators: Don't translate {volume_label} or {volume_size},
+#. they are placeholders and will be replaced. They need
+#. to be present in the translated string.
+#: config/chroot_local-includes/usr/lib/python3/dist-packages/unlock_veracrypt_volumes/volume.py:65
+#, python-brace-format
+msgid "{volume_label} ({volume_size})"
+msgstr "{volume_label} ({volume_size})"
+
+#. Translators: Don't translate {partition_name} or {partition_size},
+#. they are placeholders and will be replaced. They need
+#. to be present in the translated string.
+#: config/chroot_local-includes/usr/lib/python3/dist-packages/unlock_veracrypt_volumes/volume.py:71
+#, python-brace-format
+msgid "{partition_name} ({partition_size})"
+msgstr "{partition_name} ({partition_size})"
+
+#. Translators: Don't translate {volume_size}, it's a placeholder
+#. and will be replaced. It needs to be present in the translated
+#. string.
+#: config/chroot_local-includes/usr/lib/python3/dist-packages/unlock_veracrypt_volumes/volume.py:77
+#, python-brace-format
+msgid "{volume_size} Volume"
+msgstr "Volume de {volume_size}"
+
+#. Translators: Don't translate {volume_name}, it's a placeholder and
+#. will be replaced. It needs to be present in the translated string.
+#: config/chroot_local-includes/usr/lib/python3/dist-packages/unlock_veracrypt_volumes/volume.py:116
+#, python-brace-format
+msgid "{volume_name} (Read-Only)"
+msgstr "{volume_name} (lecture seule)"
+
+#. Translators: Don't translate {partition_name} and {container_path}, they
+#. are placeholders and will be replaced. They need to be present
+#. in the translated string.
+#: config/chroot_local-includes/usr/lib/python3/dist-packages/unlock_veracrypt_volumes/volume.py:125
+#, python-brace-format
+msgid "{partition_name} in {container_path}"
+msgstr "{partition_name} dans {container_path}"
+
+#. Translators: Don't translate {volume_name} and {path_to_file_container},
+#. they are placeholders and will be replaced. You should only have to
+#. translate
+#. this string if it makes sense to reverse the order of the placeholders.
+#: config/chroot_local-includes/usr/lib/python3/dist-packages/unlock_veracrypt_volumes/volume.py:132
+#, python-brace-format
+msgid "{volume_name} – {path_to_file_container}"
+msgstr "{volume_name} – {path_to_file_container}"
+
+#. Translators: Don't translate {partition_name} and {drive_name}, they
+#. are placeholders and will be replaced. They need to be present
+#. in the translated string.
+#: config/chroot_local-includes/usr/lib/python3/dist-packages/unlock_veracrypt_volumes/volume.py:139
+#, python-brace-format
+msgid "{partition_name} on {drive_name}"
+msgstr "{partition_name} sur {drive_name}"
+
+#. Translators: Don't translate {volume_name} and {drive_name},
+#. they are placeholders and will be replaced. You should only have to
+#. translate
+#. this string if it makes sense to reverse the order of the placeholders.
+#: config/chroot_local-includes/usr/lib/python3/dist-packages/unlock_veracrypt_volumes/volume.py:146
+#, python-brace-format
+msgid "{volume_name} – {drive_name}"
+msgstr "{volume_name} – {drive_name}"
+
+#: config/chroot_local-includes/usr/lib/python3/dist-packages/unlock_veracrypt_volumes/volume.py:234
+msgid "Wrong passphrase or parameters"
+msgstr "Mauvaise phrase de passe ou mauvais paramètres"
+
+#: config/chroot_local-includes/usr/lib/python3/dist-packages/unlock_veracrypt_volumes/volume.py:236
+msgid "Error unlocking volume"
+msgstr "Erreur de déverrouillage du volume"
+
+#. Translators: Don't translate {volume_name} or {error_message},
+#. they are placeholder and will be replaced. They need
+#. to be present in the translated string.
+#: config/chroot_local-includes/usr/lib/python3/dist-packages/unlock_veracrypt_volumes/volume.py:241
+#, python-brace-format
+msgid ""
+"Couldn't unlock volume {volume_name}:\n"
+"{error_message}"
+msgstr "Impossible de déverrouiller le volume {volume_name} :\n{error_message}"
+
+#: config/chroot_local-includes/usr/lib/python3/dist-packages/unlock_veracrypt_volumes/volume.py:343
+msgid "One or more applications are keeping the volume busy."
+msgstr "Une ou plusieurs applications tiennent le volume occupé."
+
+#. Translators: Don't translate {volume_name} or {error_message},
+#. they are placeholder and will be replaced. They need
+#. to be present in the translated string.
+#: config/chroot_local-includes/usr/lib/python3/dist-packages/unlock_veracrypt_volumes/volume.py:350
+#, python-brace-format
+msgid ""
+"Couldn't lock volume {volume_name}:\n"
+"{error_message}"
+msgstr "Impossible de verrouiller le volume {volume_name} :\n{error_message}"
+
+#: config/chroot_local-includes/usr/lib/python3/dist-packages/unlock_veracrypt_volumes/volume.py:352
+msgid "Locking the volume failed"
+msgstr "Échec de verrouillage du volume"
+
+#: config/chroot_local-includes/usr/lib/python3/dist-packages/unlock_veracrypt_volumes/volume_list.py:83
+msgid "No file containers added"
+msgstr "Aucun conteneur de fichiers n’a été ajouté"
+
+#: config/chroot_local-includes/usr/lib/python3/dist-packages/unlock_veracrypt_volumes/volume_list.py:98
+msgid "No VeraCrypt devices detected"
+msgstr "Aucun périphérique VeraCrypt détecté"
+
+#: config/chroot_local-includes/usr/lib/python3/dist-packages/unlock_veracrypt_volumes/volume_manager.py:40
+#: ../config/chroot_local-includes/usr/share/applications/unlock-veracrypt-volumes.desktop.in.h:1
+msgid "Unlock VeraCrypt Volumes"
+msgstr "Déverrouiller les volumes VeraCrypt"
+
+#: config/chroot_local-includes/usr/lib/python3/dist-packages/unlock_veracrypt_volumes/volume_manager.py:114
+msgid "Container already added"
+msgstr "Le conteneur a déjà été ajouté"
+
+#: config/chroot_local-includes/usr/lib/python3/dist-packages/unlock_veracrypt_volumes/volume_manager.py:115
+#, python-format
+msgid "The file container %s should already be listed."
+msgstr "Le conteneur de fichiers %s devrait déjà être listé."
+
+#: config/chroot_local-includes/usr/lib/python3/dist-packages/unlock_veracrypt_volumes/volume_manager.py:131
+msgid "Container opened read-only"
+msgstr "Le conteneur est ouvert en lecture seule"
+
+#. Translators: Don't translate {path}, it's a placeholder and will be
+#. replaced.
+#: config/chroot_local-includes/usr/lib/python3/dist-packages/unlock_veracrypt_volumes/volume_manager.py:133
+#, python-brace-format
+msgid ""
+"The file container {path} could not be opened with write access. It was opened read-only instead. You will not be able to modify the content of the container.\n"
+"{error_message}"
+msgstr "Le conteneur de fichiers {path} n’a pas pu être ouvert avec un accès en écriture. Il a plutôt été ouvert en lecture seule. Vous ne pourrez pas modifier le contenu du conteneur.\n{error_message}"
+
+#: config/chroot_local-includes/usr/lib/python3/dist-packages/unlock_veracrypt_volumes/volume_manager.py:138
+msgid "Error opening file"
+msgstr "Erreur d’ouverture du fichier"
+
+#: config/chroot_local-includes/usr/lib/python3/dist-packages/unlock_veracrypt_volumes/volume_manager.py:160
+msgid "Not a VeraCrypt container"
+msgstr "Ce n’est pas un conteneur VeraCrypt"
+
+#: config/chroot_local-includes/usr/lib/python3/dist-packages/unlock_veracrypt_volumes/volume_manager.py:161
+#, python-format
+msgid "The file %s does not seem to be a VeraCrypt container."
+msgstr "Le fichier %s ne semble pas être un conteneur VeraCrypt."
+
+#: config/chroot_local-includes/usr/lib/python3/dist-packages/unlock_veracrypt_volumes/volume_manager.py:163
+msgid "Failed to add container"
+msgstr "Échec d’ajout du conteneur"
+
+#: config/chroot_local-includes/usr/lib/python3/dist-packages/unlock_veracrypt_volumes/volume_manager.py:164
+#, python-format
+msgid ""
+"Could not add file container %s: Timeout while waiting for loop setup.\n"
+"Please try using the <i>Disks</i> application instead."
+msgstr "Impossible d’ajouter le conteneur de fichiers %s : délai d’attente dépassé en attendant la configuration de la boucle.\nVeuillez essayer d’utiliser l’application <i>Disques</i> à la place."
+
+#: config/chroot_local-includes/usr/lib/python3/dist-packages/unlock_veracrypt_volumes/volume_manager.py:209
+msgid "Choose File Container"
+msgstr "Choisir un conteneur de fichiers"
+
+#: config/chroot_local-includes/usr/local/sbin/unsafe-browser:40
+msgid "Launch the Unsafe Browser?"
+msgstr "Lancer le Navigateur non sécurisé ?"
+
+#: config/chroot_local-includes/usr/local/sbin/unsafe-browser:42
+msgid ""
+"The Unsafe Browser is not anonymous and the websites that you visit can see "
+"your real IP address.\\n\\nOnly use the Unsafe Browser to sign in to a "
+"network using a captive portal or browse trusted web pages on the local "
+"network."
+msgstr "Le Navigateur non sécurisé n’est pas anonyme et les sites Web que vous visitez peuvent voir votre vraie adresse IP.\\n\\nN’utilisez le Navigateur non sécurisé que pour vous connecter à un réseau grâce à un portail captif ou pour naviguer dans des pages Web fiables sur un réseau local."
+
+#: config/chroot_local-includes/usr/local/sbin/unsafe-browser:54
+msgid "Starting the Unsafe Browser..."
+msgstr "Démarrage du Navigateur non sécurisé…"
+
+#: config/chroot_local-includes/usr/local/sbin/unsafe-browser:55
+msgid "This may take a while, so please be patient."
+msgstr "Cela peut prendre du temps, veuillez être patient."
+
+#: config/chroot_local-includes/usr/local/sbin/unsafe-browser:61
+msgid "Shutting down the Unsafe Browser..."
+msgstr "Fermeture du Navigateur non sécurisé…"
+
+#: config/chroot_local-includes/usr/local/sbin/unsafe-browser:62
+msgid ""
+"This may take a while, and you may not restart the Unsafe Browser until it "
+"is properly shut down."
+msgstr "Cela peut prendre du temps et vous ne devez pas redémarrer le Navigateur non sécurisé avant sa fermeture complète."
+
+#: config/chroot_local-includes/usr/local/sbin/unsafe-browser:74
+msgid "Failed to restart Tor."
+msgstr "Échec du redémarrage de Tor."
+
+#: config/chroot_local-includes/usr/local/sbin/unsafe-browser:88
+#: ../config/chroot_local-includes/usr/share/applications/unsafe-browser.desktop.in.h:1
+#: ../config/chroot_local-includes/usr/share/tails/greeter/additional_settings.ui.in:512
+msgid "Unsafe Browser"
+msgstr "Navigateur non sécurisé"
+
+#: config/chroot_local-includes/usr/local/sbin/unsafe-browser:94
+msgid ""
+"The Unsafe Browser was not enabled in the Welcome Screen.\\n\\nTo use the Unsafe Browser, restart Tails and enable the Unsafe Browser in the additional settings of the Welcome Screen.\\n\n"
+"To always enable the Unsafe Browser, turn on the Welcome Screen feature of the Persistent Storage."
+msgstr "Le Navigateur non sécurisé n’a pas été activé sur l’écran de bienvenue.\\n\\nPour utiliser le Navigateur non sécurisé, redémarrez Tails et activez le Navigateur non sécurisé dans les paramètres supplémentaires de l’écran de bienvenue.\\n\nPour toujours activer le Navigateur non sécurisé, activez l’option de l’écran d’accueil du stockage persistant."
+
+#: config/chroot_local-includes/usr/local/sbin/unsafe-browser:103
+msgid ""
+"Another Unsafe Browser is currently running, or being cleaned up. Please "
+"retry in a while."
+msgstr "Un autre Navigateur non sécurisé est en cours d’exécution ou de nettoyage. Veuillez réessayer dans un moment."
+
+#: config/chroot_local-includes/usr/local/sbin/unsafe-browser:111
+msgid "Failed to setup chroot."
+msgstr "Échec d’exécution de chroot."
+
+#: config/chroot_local-includes/usr/local/sbin/unsafe-browser:118
+msgid "Failed to configure browser."
+msgstr "Échec de configuration du navigateur."
+
+#: config/chroot_local-includes/usr/local/sbin/unsafe-browser:124
+msgid ""
+"You are not connected to a local network yet.\\n\\nTo be able to start the "
+"Unsafe Browser, you first need to connect to a Wi-Fi, wired, or mobile "
+"network."
+msgstr "Vous n’êtes pas encore connecté à un réseau local.\\n\\nAfin de lancer le Navigateur non sécurisé, vous devez d’abord vous connecter à un réseau Wi-fi, filaire ou mobile."
+
+#: config/chroot_local-includes/usr/local/sbin/unsafe-browser:135
+msgid "Failed to run browser."
+msgstr "Échec de démarrage du navigateur."
+
+#: config/chroot_local-includes/usr/lib/python3/dist-packages/whisperBack/exceptions.py:41
+#, python-format
+msgid ""
+"The %s variable was not found in any of the configuration files "
+"/etc/whisperback/config.py, ~/.whisperback/config.py, or ./config.py"
+msgstr "La variable %s n’a été trouvée dans aucun des fichiers de configuration /etc/whisperback/config.py, ~/.whisperback/config.py ni ./config.py"
+
+#: config/chroot_local-includes/usr/lib/python3/dist-packages/whisperBack/gui.py:114
+msgid "Name of the affected software"
+msgstr "Nom du logiciel concerné"
+
+#: config/chroot_local-includes/usr/lib/python3/dist-packages/whisperBack/gui.py:116
+msgid "Exact steps to reproduce the error"
+msgstr "Étapes exactes pour reproduire l’erreur"
+
+#: config/chroot_local-includes/usr/lib/python3/dist-packages/whisperBack/gui.py:118
+msgid "Actual result and description of the error"
+msgstr "Résultat observé et description de l’erreur"
+
+#: config/chroot_local-includes/usr/lib/python3/dist-packages/whisperBack/gui.py:120
+msgid "Desired result"
+msgstr "Résultat souhaité"
+
+#: config/chroot_local-includes/usr/lib/python3/dist-packages/whisperBack/gui.py:133
+msgid "Unable to load a valid configuration."
+msgstr "Impossible de charger une configuration valide."
+
+#: config/chroot_local-includes/usr/lib/python3/dist-packages/whisperBack/gui.py:170
+msgid "Sending mail..."
+msgstr "Envoi du courriel…"
+
+#: config/chroot_local-includes/usr/lib/python3/dist-packages/whisperBack/gui.py:171
+msgid "Sending mail"
+msgstr "Envoi du courriel"
+
+#: config/chroot_local-includes/usr/lib/python3/dist-packages/whisperBack/gui.py:173
+msgid "This could take a while..."
+msgstr "Cela peut prendre du temps…"
+
+#: config/chroot_local-includes/usr/lib/python3/dist-packages/whisperBack/gui.py:189
+msgid "The contact email address doesn't seem valid."
+msgstr "L’adresse courriel de contact ne semble pas valide."
+
+#: config/chroot_local-includes/usr/lib/python3/dist-packages/whisperBack/gui.py:206
+msgid "Unable to send the mail: SMTP error."
+msgstr "Impossible d’envoyer le courriel : erreur SMTP."
+
+#: config/chroot_local-includes/usr/lib/python3/dist-packages/whisperBack/gui.py:208
+msgid "Unable to connect to the server."
+msgstr "Impossible de se connecter au serveur."
+
+#: config/chroot_local-includes/usr/lib/python3/dist-packages/whisperBack/gui.py:210
+msgid "Unable to create or to send the mail."
+msgstr "Impossible de créer ni d’envoyer le courriel."
+
+#: config/chroot_local-includes/usr/lib/python3/dist-packages/whisperBack/gui.py:213
+msgid ""
+"\n"
+"\n"
+"The bug report could not be sent, likely due to network problems. Please try to reconnect to the network and click send again.\n"
+"\n"
+"If it does not work, you will be offered to save the bug report."
+msgstr "\n\nLe relevé de bogue n’a pas pu être envoyé, probablement à cause de problèmes de réseau. Veuillez essayer de vous reconnecter au réseau et de recliquer sur envoyer.\n\nSi cela ne fonctionne pas, l’on vous proposera d’enregistrer le relevé de bogue."
+
+#: config/chroot_local-includes/usr/lib/python3/dist-packages/whisperBack/gui.py:226
+msgid "Your message has been sent."
+msgstr "Votre message a été envoyé."
+
+#: config/chroot_local-includes/usr/lib/python3/dist-packages/whisperBack/gui.py:233
+msgid "An error occured during encryption."
+msgstr "Une erreur est survenue lors du chiffrement."
+
+#: config/chroot_local-includes/usr/lib/python3/dist-packages/whisperBack/gui.py:253
+#, python-format
+msgid "Unable to save %s."
+msgstr "Impossible d’enregistrer %s."
+
+#: config/chroot_local-includes/usr/lib/python3/dist-packages/whisperBack/gui.py:276
+#, python-format
+msgid ""
+"The bug report could not be sent, likely due to network problems.\n"
+"\n"
+"As a work-around you can save the bug report as a file on a USB drive and try to send it to us at %s from your email account using another system. Note that your bug report will not be anonymous when doing so unless you take further steps yourself (e.g. using Tor with a throw-away email account).\n"
+"\n"
+"Do you want to save the bug report to a file?"
+msgstr "Le relevé de bogue n’a pas pu être envoyé, probablement à cause de problèmes de réseau.\n\nPour contourner le problème, vous pouvez enregistrer le relevé de bogue sous forme de fichier sur une clé USB et essayer de nous l’envoyer à %s à partir de votre compte de courriel en utilisant un autre système. Prenez note que votre relevé de bogue ne sera pas anonyme de cette façon, à moins que vous ne preniez des précautions supplémentaires (p. ex. en utilisant Tor avec un compte de courriel jetable).\n\nVoulez-vous enregistrer le relevé de bogue dans un fichier ?"
+
+#: config/chroot_local-includes/usr/lib/python3/dist-packages/whisperBack/gui.py:338
+#: ../config/chroot_local-includes/usr/share/whisperback/whisperback.ui.in:280
+msgid "WhisperBack"
+msgstr "WhisperBack"
+
+#: config/chroot_local-includes/usr/lib/python3/dist-packages/whisperBack/gui.py:339
+#: ../config/chroot_local-includes/usr/share/whisperback/whisperback.ui.in:12
+msgid "Send feedback in an encrypted mail."
+msgstr "Envoyez votre rétroaction dans un courriel chiffré."
+
+#: config/chroot_local-includes/usr/lib/python3/dist-packages/whisperBack/gui.py:342
+msgid "Copyright © 2009-2018 Tails developers (tails(a)boum.org)"
+msgstr "Tous droits réservés © 2009 à 2018 Les développeurs de Tails (tails(a)boum.org)"
+
+#: config/chroot_local-includes/usr/lib/python3/dist-packages/whisperBack/gui.py:343
+msgid "Tails developers <tails(a)boum.org>"
+msgstr "Les développeurs de Tails <tails(a)boum.org>"
+
+#: config/chroot_local-includes/usr/lib/python3/dist-packages/whisperBack/gui.py:344
+msgid "translator-credits"
+msgstr "crédits aux traducteurs"
+
+#: config/chroot_local-includes/usr/lib/python3/dist-packages/whisperBack/gui.py:377
+msgid "This doesn't seem to be a valid URL or OpenPGP key."
+msgstr "Cela ne semble être ni une URL ni une clé OpenPGP valide."
+
+#: config/chroot_local-includes/usr/lib/python3/dist-packages/whisperBack/whisperback.py:63
+#, python-format
+msgid "Invalid contact email: %s"
+msgstr "L’adresse courriel de contact est invalide : %s"
+
+#: config/chroot_local-includes/usr/lib/python3/dist-packages/whisperBack/whisperback.py:83
+#, python-format
+msgid "Invalid contact OpenPGP key: %s"
+msgstr "La clé OpenPGP du contact est invalide : %s"
+
+#: config/chroot_local-includes/usr/lib/python3/dist-packages/whisperBack/whisperback.py:85
+msgid "Invalid contact OpenPGP public key block"
+msgstr "Le bloc de clé publique OpenPGP du contact est invalide"
+
+#: config/chroot_local-includes/usr/local/bin/tca:140
+msgid "You turned on Offline Mode in the Welcome Screen."
+msgstr "Vous avez activé le mode Hors ligne dans l’écran de bienvenue."
+
+#: config/chroot_local-includes/usr/local/bin/tca:141
+msgid "It is impossible to connect to Tor in Offline Mode."
+msgstr "Il est impossible de se connecter à Tor en mode Hors ligne."
+
+#: config/chroot_local-includes/usr/local/bin/tca:142
+msgid ""
+"To connect to Tor and the Internet, restart Tails without Offline Mode."
+msgstr "Pour se connecter à Tor et à Internet, redémarrez Tails après avoir désactivé le mode Hors ligne."
+
+#: ../config/chroot_local-includes/etc/skel/Desktop/Report_an_error.desktop.in.h:1
+msgid "Report an error"
+msgstr "Signaler une erreur"
+
+#: ../config/chroot_local-includes/etc/skel/Desktop/tails-documentation.desktop.in.h:1
+#: ../config/chroot_local-includes/usr/share/applications/tails-documentation.desktop.in.h:1
+msgid "Tails documentation"
+msgstr "Documentation de Tails"
+
+#: ../config/chroot_local-includes/usr/share/applications/root-terminal.desktop.in.h:1
+msgid "Root Terminal"
+msgstr "Terminal superutilisateur"
+
+#: ../config/chroot_local-includes/usr/share/applications/root-terminal.desktop.in.h:2
+msgid "Opens a terminal as the root user, using gksu to ask for the password"
+msgstr "Ouvre un terminal en tant que superutilisateur, en utilisant gksu pour demander le mot de passe"
+
+#: ../config/chroot_local-includes/usr/share/applications/tails-documentation.desktop.in.h:2
+msgid "Learn how to use Tails"
+msgstr "Apprendre à utiliser Tails"
+
+#: ../config/chroot_local-includes/usr/share/applications/tails-about.desktop.in.h:2
+msgid "Learn more about Tails"
+msgstr "En apprendre davantage sur Tails"
+
+#: ../config/chroot_local-includes/usr/share/applications/tails-installer.desktop.in.h:2
+msgid "Install, clone, upgrade Tails"
+msgstr "Installer, cloner, mettre Tails à niveau"
+
+#: ../config/chroot_local-includes/usr/share/applications/tails-persistence-delete.desktop.in.h:1
+msgid "Delete persistent volume"
+msgstr "Supprimer le volume persistant"
+
+#: ../config/chroot_local-includes/usr/share/applications/tails-persistence-delete.desktop.in.h:2
+msgid "Delete the persistent volume and its content"
+msgstr "Supprimer le volume persistant et son contenu"
+
+#: ../config/chroot_local-includes/usr/share/applications/tails-persistence-setup.desktop.in.h:1
+msgid "Configure persistent volume"
+msgstr "Configurer le volume persistant"
+
+#: ../config/chroot_local-includes/usr/share/applications/tails-persistence-setup.desktop.in.h:2
+msgid ""
+"Configure which files and application configuration are saved between "
+"working sessions"
+msgstr "Configurer quels fichiers et configurations d’application sont enregistrés entre les sessions de travail"
+
+#: ../config/chroot_local-includes/usr/share/applications/tca.desktop.in.h:2
+msgid "Connect Tails to the Tor network"
+msgstr "Connecter Tails au réseau Tor"
+
+#: ../config/chroot_local-includes/usr/share/applications/tor-browser.desktop.in.h:1
+msgid "Tor Browser"
+msgstr "Navigateur Tor"
+
+#: ../config/chroot_local-includes/usr/share/applications/tor-browser.desktop.in.h:2
+msgid "Anonymous Web Browser"
+msgstr "Navigateur Web anonyme"
+
+#: ../config/chroot_local-includes/usr/share/applications/unsafe-browser.desktop.in.h:2
+msgid "Browse the World Wide Web without anonymity"
+msgstr "Naviguer sur le Toile sans anonymat"
+
+#: ../config/chroot_local-includes/usr/share/applications/unsafe-browser.desktop.in.h:3
+msgid "Unsafe Web Browser"
+msgstr "Navigateur Web non sécurisé"
+
+#: ../config/chroot_local-includes/usr/share/applications/unlock-veracrypt-volumes.desktop.in.h:2
+msgid "Mount VeraCrypt encrypted file containers and devices"
+msgstr "Monter les conteneurs de fichiers et les périphériques chiffrés VeraCrypt"
+
+#: ../config/chroot_local-includes/usr/share/applications/org.boum.tails.additional-software-config.desktop.in.h:2
+msgid ""
+"Configure the additional software installed from your persistent storage "
+"when starting Tails"
+msgstr "Configurer les logiciels supplémentaires installés à partir de votre stockage persistant lors du démarrage de Tails"
+
+#: ../config/chroot_local-includes/usr/share/applications/whisperback.desktop.in.h:1
+msgid "WhisperBack Error Reporting"
+msgstr "Signalement d’erreurs avec WhisperBack"
+
+#: ../config/chroot_local-includes/usr/share/applications/whisperback.desktop.in.h:2
+msgid "Send feedback via encrypted e-mail"
+msgstr "Envoyer une rétroaction par courriel chiffré"
+
+#: ../config/chroot_local-includes/usr/share/applications/whisperback.desktop.in.h:3
+msgid "feedback;bug;report;tails;error;"
+msgstr "feedback;rétroaction;commentaire;bogue;bug;relevé;rapport;tails;erreur;"
+
+#: ../config/chroot_local-includes/usr/share/desktop-directories/Tails.directory.in.h:2
+msgid "Tails specific tools"
+msgstr "Outils spécifiques à Tails"
+
+#: ../config/chroot_local-includes/usr/share/polkit-1/actions/org.boum.tails.root-terminal.policy.in.h:1
+msgid "To start a Root Terminal, you need to authenticate."
+msgstr "Vous devez vous authentifier pour lancer un Terminal administrateur."
+
+#: ../config/chroot_local-includes/usr/share/polkit-1/actions/org.boum.tails.additional-software.policy.in.h:1
+msgid "Remove an additional software package"
+msgstr "Enlever un paquet logiciel supplémentaire"
+
+#: ../config/chroot_local-includes/usr/share/polkit-1/actions/org.boum.tails.additional-software.policy.in.h:2
+msgid ""
+"Authentication is required to remove a package from your additional software"
+" ($(command_line))"
+msgstr "Une authentification est requise afin d’enlever un paquet de vos logiciels supplémentaires ($(command_line))"
+
+#: ../config/chroot_local-includes/usr/share/tails/greeter/additional_settings.ui.in:18
+#: ../config/chroot_local-includes/usr/share/tails/greeter/additional_settings.ui.in:56
+#: ../config/chroot_local-includes/usr/share/tails/greeter/main.ui.in:625
+msgid "Administration Password"
+msgstr "Mot de passe d’administration"
+
+#: ../config/chroot_local-includes/usr/share/tails/greeter/additional_settings.ui.in:34
+msgid ""
+"Set up an administration password if you need to perform administrative "
+"tasks. Otherwise, the administration password is disabled for better "
+"security."
+msgstr "Définir un mot de passe d’administration si vous devez effectuer des tâches administratives. Sinon, le mot de passe d’administration est désactivé pour une sécurité accrue."
+
+#: ../config/chroot_local-includes/usr/share/tails/greeter/additional_settings.ui.in:69
+msgid "Enter an administration password"
+msgstr "Saisir un mot de passe d’administration"
+
+#: ../config/chroot_local-includes/usr/share/tails/greeter/additional_settings.ui.in:107
+msgid "Confirm your administration password"
+msgstr "Confirmer votre mot de passe d’administration"
+
+#: ../config/chroot_local-includes/usr/share/tails/greeter/additional_settings.ui.in:124
+msgid "Disable"
+msgstr "Désactiver"
+
+#: ../config/chroot_local-includes/usr/share/tails/greeter/additional_settings.ui.in:154
+#: ../config/chroot_local-includes/usr/share/tails/greeter/main.ui.in:629
+msgid "MAC Address Anonymization"
+msgstr "Anonymisation de l’adresse MAC"
+
+#: ../config/chroot_local-includes/usr/share/tails/greeter/additional_settings.ui.in:170
+msgid ""
+"MAC address anonymization hides the serial number of your network interface "
+"(Wi-Fi or wired) from the local network. Anonymizing MAC addresses is "
+"generally safer as it helps you hide your geographical location. But it "
+"might also create connectivity problems or look suspicious."
+msgstr "L’anonymisation de l’adresse MAC dissimule au réseau local le numéro de série de votre interface réseau (Wi-Fi ou filaire). L’anonymisation de l’adresse MAC est généralement plus sûre, car elle vous aide à dissimuler votre position géographique. Mais elle peut aussi créer des problèmes de connectivité et sembler suspecte."
+
+#: ../config/chroot_local-includes/usr/share/tails/greeter/additional_settings.ui.in:212
+msgid "Anonymize all MAC addresses (default)"
+msgstr "Anonymiser toutes les adresses MAC (par défaut)"
+
+#: ../config/chroot_local-includes/usr/share/tails/greeter/additional_settings.ui.in:258
+msgid "Don't anonymize MAC addresses"
+msgstr "Ne pas anonymiser les adresses MAC"
+
+#: ../config/chroot_local-includes/usr/share/tails/greeter/additional_settings.ui.in:311
+#: ../config/chroot_local-includes/usr/share/tails/greeter/main.ui.in:633
+msgid "Network Configuration"
+msgstr "Configuration du réseau"
+
+#: ../config/chroot_local-includes/usr/share/tails/greeter/additional_settings.ui.in:327
+msgid ""
+"We replaced this additional setting in Tails 4.19 (June 2021) with a Tor Connection assistant integrated in the desktop.\n"
+"\n"
+"You will be asked whether you want to use Tor bridges when connecting to Tor after starting Tails.\n"
+"\n"
+"If you want to work offline, enable the Offline Mode in the additional settings."
+msgstr "Dans Tails 4.19 (juin 2021), nous avons remplacé ce paramètre supplémentaire par un assistant de connexion à Tor intégré au bureau.\n\nIl vous sera demandé si vous voulez utiliser des ponts Tor lors de votre connexion à Tor après avoir démarré Tails.\n\nSi vous voulez travailler hors ligne, activez le mode Hors ligne dans les paramètres supplémentaires."
+
+#: ../config/chroot_local-includes/usr/share/tails/greeter/additional_settings.ui.in:357
+msgid "Offline Mode"
+msgstr "Mode Hors ligne"
+
+#: ../config/chroot_local-includes/usr/share/tails/greeter/additional_settings.ui.in:373
+msgid ""
+"If you want to work completely offline, you can disable all networking for "
+"increased security."
+msgstr "Si vous voulez travailler complètement hors ligne, pour une sécurité accrue vous pouvez désactiver la mise en réseau."
+
+#: ../config/chroot_local-includes/usr/share/tails/greeter/additional_settings.ui.in:528
+msgid ""
+"The Unsafe Browser allows you to sign in to a network using a captive portal.\n"
+"\n"
+"A captive portal is a web page that is displayed before you can access the Internet. Captive portals usually require you to log in to the network or enter information such as an email address.\n"
+"\n"
+"The Unsafe Browser is not anonymous and can deanonymize you. Use it only to sign in to networks."
+msgstr "Le Navigateur non sécurisé vous permet de vous connecter à un réseau grâce à un portail captif.\n\nUn portail captif est une page Web qui est affichée avant que vous puissiez accéder à Internet. Les portails captifs exigent habituellement que vous vous connectiez au réseau ou que vous saisissiez des renseignements tels qu’une adresse courriel.\n\nLe Navigateur non sécurisé n’est pas anonyme et peut divulguer votre identité. Ne l’utilisez que pour vous connecter à des réseaux."
+
+#: ../config/chroot_local-includes/usr/share/tails/greeter/additional_settings.ui.in:574
+msgid "Disable the Unsafe Browser (default)"
+msgstr "Désactiver le Navigateur non sécurisé (par défaut)"
+
+#: ../config/chroot_local-includes/usr/share/tails/greeter/additional_settings.ui.in:619
+msgid "Enable the Unsafe Browser"
+msgstr "Activer le Navigateur non sécurisé"
+
+#: ../config/chroot_local-includes/usr/share/tails/greeter/main.ui.in:100
+msgid "Settings were loaded from the persistent storage."
+msgstr "Les paramètres ont été chargés du stockage persistant."
+
+#: ../config/chroot_local-includes/usr/share/tails/greeter/main.ui.in:152
+msgid "Welcome to Tails!"
+msgstr "Bienvenue dans Tails"
+
+#: ../config/chroot_local-includes/usr/share/tails/greeter/main.ui.in:186
+msgid "Language & Region"
+msgstr "Langue et région"
+
+#: ../config/chroot_local-includes/usr/share/tails/greeter/main.ui.in:222
+msgid "Default Settings"
+msgstr "Paramètres par défaut"
+
+#: ../config/chroot_local-includes/usr/share/tails/greeter/main.ui.in:285
+msgid "Encrypted _Persistent Storage"
+msgstr "_Stockage persistant chiffré"
+
+#. The label for this placeholder text is not very big, so keep this string
+#. short.
+#: ../config/chroot_local-includes/usr/share/tails/greeter/main.ui.in:379
+msgid "Enter your passphrase to unlock the persistent storage"
+msgstr "Saisissez votre phrase de passe pour déverrouiller le stockage persistant"
+
+#: ../config/chroot_local-includes/usr/share/tails/greeter/main.ui.in:427
+msgid "Your persistent storage is unlocked. Restart Tails to lock it again."
+msgstr "Votre stockage persistant est déverrouillé. Redémarrez Tails pour le verrouiller à nouveau."
+
+#: ../config/chroot_local-includes/usr/share/tails/greeter/main.ui.in:465
+msgid "_Additional Settings"
+msgstr "_Paramètres supplémentaires"
+
+#: ../config/chroot_local-includes/usr/share/tails/greeter/main.ui.in:548
+msgid "Add an additional setting"
+msgstr "Ajouter un paramètre supplémentaire"
+
+#: ../config/chroot_local-includes/usr/share/tails/greeter/main.ui.in:597
+msgid ""
+"The default settings are safe in most situations. To add a custom setting, "
+"press the \"+\" button below."
+msgstr "Les paramètres par défaut sont sûrs dans la plupart des cas. Pour ajouter un paramètre personnalisé, appuyer sur le bouton « + » ci-dessous."
+
+#: ../config/chroot_local-includes/usr/share/tails/greeter/main.ui.in:641
+msgid "Shutdown"
+msgstr "Éteindre"
+
+#: ../config/chroot_local-includes/usr/share/tails/greeter/main.ui.in:652
+msgid "_Start Tails"
+msgstr "_Démarrer Tails"
+
+#: ../config/chroot_local-includes/usr/share/tails/unlock-veracrypt-volumes/main.ui.in:61
+msgid "File Containers"
+msgstr "Conteneurs de fichiers"
+
+#: ../config/chroot_local-includes/usr/share/tails/unlock-veracrypt-volumes/main.ui.in:80
+msgid "_Add"
+msgstr "_Ajouter"
+
+#: ../config/chroot_local-includes/usr/share/tails/unlock-veracrypt-volumes/main.ui.in:86
+msgid "Add a file container"
+msgstr "Ajouter un conteneur de fichiers"
+
+#: ../config/chroot_local-includes/usr/share/tails/unlock-veracrypt-volumes/main.ui.in:103
+msgid "Partitions and Drives"
+msgstr "Partitions et lecteurs"
+
+#: ../config/chroot_local-includes/usr/share/tails/unlock-veracrypt-volumes/main.ui.in:121
+msgid ""
+"This application is not affiliated with or endorsed by the VeraCrypt project"
+" or IDRIX."
+msgstr "Cette application n’est ni affiliée avec le projet VeraCrypt ou IDRIX ni approuvée par ces derniers."
+
+#: ../config/chroot_local-includes/usr/share/tails/unlock-veracrypt-volumes/volume.ui.in:29
+msgid "_Open"
+msgstr "_Ouvrir"
+
+#: ../config/chroot_local-includes/usr/share/tails/unlock-veracrypt-volumes/volume.ui.in:38
+msgid "Lock this volume"
+msgstr "Verrouiller ce volume"
+
+#: ../config/chroot_local-includes/usr/share/tails/unlock-veracrypt-volumes/volume.ui.in:52
+msgid "_Unlock"
+msgstr "_Déverrouiller"
+
+#: ../config/chroot_local-includes/usr/share/tails/unlock-veracrypt-volumes/volume.ui.in:61
+msgid "Detach this volume"
+msgstr "Détacher ce volume"
+
+#: ../config/chroot_local-includes/usr/share/tails-installer/tails-installer.ui.in:265
+msgid "Target USB stick:"
+msgstr "Clé USB cible :"
+
+#: ../config/chroot_local-includes/usr/share/tails-installer/tails-installer.ui.in:341
+msgid "Reinstall (delete all data)"
+msgstr "Réinstaller (supprimer toutes les données)"
+
+#: ../config/chroot_local-includes/usr/share/whisperback/whisperback.ui.in:11
+msgid "Copyright © 2009-2018 tails(a)boum.org"
+msgstr "Tous droits réservés © 2009 à 2018 tails(a)boum.org"
+
+#: ../config/chroot_local-includes/usr/share/whisperback/whisperback.ui.in:15
+msgid ""
+"WhisperBack - Send feedback in an encrypted mail\n"
+"Copyright (C) 2009-2018 Tails developers <tails(a)boum.org>\n"
+"\n"
+"This program is free software; you can redistribute it and/or modify\n"
+"it under the terms of the GNU General Public License as published by\n"
+"the Free Software Foundation; either version 3 of the License, or (at\n"
+"your option) any later version.\n"
+"\n"
+"This program is distributed in the hope that it will be useful, but\n"
+"WITHOUT ANY WARRANTY; without even the implied warranty of\n"
+"MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU\n"
+"General Public License for more details.\n"
+"\n"
+"You should have received a copy of the GNU General Public License\n"
+"along with this program. If not, see <http://www.gnu.org/licenses/>.\n"
+msgstr "WhisperBack – Envoyez votre rétroaction dans un courriel chiffré\nTous droits réservés © 2009 à 2018 Les développeurs de Tails <tails(a)boum.org>\n\nCe programme est un logiciel libre ; vous pouvez le redistribuer ou le modifier suivant les conditions de la licence publique générale GNU telle que publiée par la « Free Software Foundation » ; soit la version 3 de la licence, soit (au choix) toute version ultérieure.\n\nCe programme est distribué dans l’espoir d’être utile, mais SANS AUCUNE GARANTIE ; sans même la garantie implicite de COMMERCIALISATION ou D’ADAPTATION À UN USAGE PARTICULIER. Voir la licence publique générale GNU pour plus de précisions.\n\nVous devriez avoir reçu un exemplaire de la licence publique générale GNU avec ce programme. Sinon, voir <https://www.gnu.org/licenses/licenses.fr.html>.\n"
+
+#: ../config/chroot_local-includes/usr/share/whisperback/whisperback.ui.in:122
+msgid ""
+"If you want us to encrypt messages when we respond to you, add your key ID, "
+"a link to your key, or the key as a public key block:"
+msgstr "Si vous voulez que l’on chiffre les courriels quand nous vous répondons, ajoutez votre ID de clé, un lien vers votre clé, ou la clé comme bloc de clé publique :"
+
+#: ../config/chroot_local-includes/usr/share/whisperback/whisperback.ui.in:308
+msgid "Summary"
+msgstr "Résumé"
+
+#: ../config/chroot_local-includes/usr/share/whisperback/whisperback.ui.in:337
+#: ../config/chroot_local-includes/usr/share/whisperback/whisperback.ui.in:485
+msgid "Bug description"
+msgstr "Description du bogue"
+
+#: ../config/chroot_local-includes/usr/share/whisperback/whisperback.ui.in:378
+msgid "Help:"
+msgstr "Aide :"
+
+#: ../config/chroot_local-includes/usr/share/whisperback/whisperback.ui.in:388
+msgid "Read our bug reporting guidelines."
+msgstr "Consulter nos directives de signalement de bogues."
+
+#: ../config/chroot_local-includes/usr/share/whisperback/whisperback.ui.in:416
+msgid "Email address (if you want an answer from us)"
+msgstr "Adresse courriel (si vous souhaitez une réponse de notre part)"
+
+#: ../config/chroot_local-includes/usr/share/whisperback/whisperback.ui.in:445
+msgid "optional PGP key"
+msgstr "clé PGP facultative"
+
+#: ../config/chroot_local-includes/usr/share/whisperback/whisperback.ui.in:470
+msgid "Please know that we are not able to reply to every bug report."
+msgstr "Sachez que nous ne sommes pas en mesure de répondre à tous les relevés de bogue."
+
+#: ../config/chroot_local-includes/usr/share/whisperback/whisperback.ui.in:502
+#: ../config/chroot_local-includes/usr/share/whisperback/whisperback.ui.in:613
+msgid "Technical details to include"
+msgstr "Détails techniques à inclure"
+
+#: ../config/chroot_local-includes/usr/share/whisperback/whisperback.ui.in:540
+msgid "headers"
+msgstr "en-têtes"
+
+#: ../config/chroot_local-includes/usr/share/whisperback/whisperback.ui.in:588
+msgid "debugging info"
+msgstr "renseignements de débogage"
+
+#: ../config/chroot_local-includes/usr/share/whisperback/whisperback.ui.in:680
+msgid "Send"
+msgstr "Envoyer"
+
+#: ../config/chroot_local-includes/usr/local/share/mime/packages/unlock-veracrypt-volumes.xml.in.h:1
+msgid "TrueCrypt/VeraCrypt container"
+msgstr "Conteneur TrueCrypt/VeraCrypt"
+
+#: ../config/chroot_local-includes/usr/share/tails/tca/main.ui.in:55
+#: ../config/chroot_local-includes/usr/share/tails/tca/main.ui.in:896
+msgid "Configure a Tor bridge"
+msgstr "Configurer un pont Tor"
+
+#: ../config/chroot_local-includes/usr/share/tails/tca/main.ui.in:71
+msgid ""
+"Bridges are secret Tor relays. Use a bridge as your first Tor relay if "
+"accessing Tor is blocked from where you are."
+msgstr "Les ponts sont des relais Tor secrets. Utilisez un pont comme premier relais Tor si l’accès à Tor est bloqué où vous vous situez."
+
+#: ../config/chroot_local-includes/usr/share/tails/tca/main.ui.in:87
+msgid "<a href=\"doc/anonymous_internet/tor\">Learn more about Tor bridges</a>"
+msgstr "<a href=\"doc/anonymous_internet/tor\">En apprendre davantage sur les ponts de Tor</a>"
+
+#: ../config/chroot_local-includes/usr/share/tails/tca/main.ui.in:123
+msgid "Use a default bridge"
+msgstr "Utiliser un pont par défaut"
+
+#: ../config/chroot_local-includes/usr/share/tails/tca/main.ui.in:142
+msgid "obfs4 (recommended)"
+msgstr "obfs4 (recommandé))"
+
+#: ../config/chroot_local-includes/usr/share/tails/tca/main.ui.in:143
+msgid "meek"
+msgstr "meek"
+
+#: ../config/chroot_local-includes/usr/share/tails/tca/main.ui.in:166
+#: ../config/chroot_local-includes/usr/share/tails/tca/main.ui.in:1069
+msgid "None"
+msgstr "Aucune"
+
+#: ../config/chroot_local-includes/usr/share/tails/tca/main.ui.in:194
+msgid "Request a new bridge"
+msgstr "Demander un nouveau pont"
+
+#: ../config/chroot_local-includes/usr/share/tails/tca/main.ui.in:227
+msgid "Type in a bridge that I already know"
+msgstr "Indiquer un pont que je connais déjà"
+
+#: ../config/chroot_local-includes/usr/share/tails/tca/main.ui.in:245
+msgid ""
+"Currently in Tails, only obfs4 bridges hide that you are using Tor.\n"
+"\n"
+"obfs4 bridges start with the word 'obfs4'.\n"
+"\n"
+"To request obfs4 bridges, you can send an empty email to\n"
+"<tt>bridges(a)torproject.org</tt> from a Gmail or Riseup email address.\n"
+msgstr "Actuellement dans Tails, seuls les ponts obfs4 dissimulent le fait que vous utilisez Tor.\n\nLes ponts obfs4 commencent par le mot « obfs4 ».\n\nPour demander des ponts obfs4, vous pouvez envoyer un courriel vide à <tt>bridges(a)torproject.org</tt> à partir d’une adresse courriel Gmail ou Riseup.\n"
+
+#: ../config/chroot_local-includes/usr/share/tails/tca/main.ui.in:363
+#: ../config/chroot_local-includes/usr/share/tails/tca/main.ui.in:702
+#: ../config/chroot_local-includes/usr/share/tails/tca/main.ui.in:1110
+msgid "Connect to _Tor"
+msgstr "Se connecter à _Tor"
+
+#: ../config/chroot_local-includes/usr/share/tails/tca/main.ui.in:410
+msgid "Error connecting to Tor"
+msgstr "Erreur de connexion à Tor"
+
+#: ../config/chroot_local-includes/usr/share/tails/tca/main.ui.in:433
+msgid "• Public network"
+msgstr "• Réseau public"
+
+#: ../config/chroot_local-includes/usr/share/tails/tca/main.ui.in:453
+msgid ""
+"If you are in a shop, hotel, or airport, you might need to sign in to the "
+"local network using a captive portal."
+msgstr "Si vous vous trouvez dans une boutique, un hôtel ou un aéroport, vous devrez peut-être vous connecter au réseau local grâce à un portail captif."
+
+#: ../config/chroot_local-includes/usr/share/tails/tca/main.ui.in:466
+msgid "Try Signing in to the Network"
+msgstr "Essayez de vous connecter au réseau"
+
+#: ../config/chroot_local-includes/usr/share/tails/tca/main.ui.in:503
+msgid "• Local proxy"
+msgstr "• Mandataire local"
+
+#: ../config/chroot_local-includes/usr/share/tails/tca/main.ui.in:523
+msgid ""
+"If you are on a corporate or university network, you might need to configure"
+" a local proxy."
+msgstr "Si vous utilisez un réseau d’entreprise ou d’université, vous devrez peut-être configurer un serveur mandataire local."
+
+#: ../config/chroot_local-includes/usr/share/tails/tca/main.ui.in:536
+msgid "Configure a Local _Proxy"
+msgstr "Configurer un _mandataire local"
+
+#: ../config/chroot_local-includes/usr/share/tails/tca/main.ui.in:574
+msgid "• Bridges over email"
+msgstr "• Ponts par courriel"
+
+#: ../config/chroot_local-includes/usr/share/tails/tca/main.ui.in:594
+msgid ""
+"To request new Tor bridges, you can also:\n"
+"\n"
+"1. Send an empty email to <tt>bridges(a)torproject.org</tt> from a Gmail or Riseup email address.\n"
+"\n"
+"2. Type below the bridges that you received by email."
+msgstr "Pour demander de nouveaux ponts Tor, vous pouvez aussi :\n\n1. Envoyer un courriel vide à <tt>bridges(a)torproject.org</tt> à partir d’une adresse courriel Gmail ou Riseup.\n\n2. Saisir ci-dessous les ponts que vous avez reçus par courriel."
+
+#: ../config/chroot_local-includes/usr/share/tails/tca/main.ui.in:740
+#: ../config/chroot_local-includes/usr/share/tails/tca/main.ui.in:1154
+msgid ""
+"Everything you do on the Internet from Tails goes through the Tor network."
+msgstr "Toute votre activité sur Internet à partir de Tails passe par le réseau Tor."
+
+#: ../config/chroot_local-includes/usr/share/tails/tca/main.ui.in:755
+#: ../config/chroot_local-includes/usr/share/tails/tca/main.ui.in:1169
+msgid ""
+"Tor encrypts and anonymizes your connection by passing it through 3 relays.\n"
+"Tor relays are servers operated by different organizations and volunteers around the world."
+msgstr "Tor chiffre et anonymise votre connexion en passant par trois relais.\nLes relais Tor sont des serveurs exploités par différents organismes et bénévoles dans le monde entier."
+
+#: ../config/chroot_local-includes/usr/share/tails/tca/main.ui.in:793
+msgid "<b>Connect to Tor automatically (easier)</b>"
+msgstr "<b>Se connecter à Tor automatiquement (plus facile)</b>"
+
+#: ../config/chroot_local-includes/usr/share/tails/tca/main.ui.in:841
+msgid ""
+"We recommend connecting to Tor automatically if you are on a public Wi-Fi "
+"network or if many people in your country use Tor to circumvent censorship."
+msgstr "Nous vous recommandons de vous connecter à Tor automatiquement si vous vous trouvez sur un réseau Wi-Fi public, ou si de nombreuses personnes utilisent Tor dans votre pays pour contourner la censure."
+
+#: ../config/chroot_local-includes/usr/share/tails/tca/main.ui.in:859
+msgid ""
+"Tails will try different ways of connecting to Tor until it succeeds.\n"
+"\n"
+"Someone monitoring your Internet connection could identify these attempts as coming from a Tails user."
+msgstr "Tails essaiera différentes façons de se connecter à Tor jusqu’à ce qu’il réussisse. Quelqu’un qui surveillerait votre connexion à Internet pourrait déterminer que ces tentatives proviennent d’un utilisateur de Tails."
+
+#: ../config/chroot_local-includes/usr/share/tails/tca/main.ui.in:941
+msgid ""
+"Tor bridges are secret Tor relays. Use a bridge as your first Tor relay if connections to Tor are blocked, for example in some countries, by some public networks, or by some parental controls.\n"
+"\n"
+"Choose this option if you already know that you need bridges. Otherwise, Tails will autodetect whether you need bridges to connect to Tor from your local network."
+msgstr "Les ponts de Tor sont des relais Tor secrets. Utilisez un pont comme premier relais Tor si les connexions à Tor sont bloquées, par exemple dans certains pays, par certains réseaux publics, ou encore par des contrôles parentaux.\n\nChoisissez cette option si vous savez déjà que vous avez besoin de ponts. Autrement, Tails détectera automatiquement si vous en avez besoin pour vous connecter à Tor de votre réseau local."
+
+#: ../config/chroot_local-includes/usr/share/tails/tca/main.ui.in:984
+msgid "<b>Hide to my local network that I'm connecting to Tor (safer)</b>"
+msgstr "<b>Dissimuler à mon réseau local que je me connecte à Tor (plus sûr)</b>"
+
+#: ../config/chroot_local-includes/usr/share/tails/tca/main.ui.in:1032
+msgid ""
+"You might need to go unnoticed if using Tor could look suspicious to someone"
+" who monitors your Internet connection."
+msgstr "Vous pourriez vouloir passer inaperçu si l’utilisation de Tor peut sembler suspecte à quiconque surveillerait votre connexion à Internet."
+
+#: ../config/chroot_local-includes/usr/share/tails/tca/main.ui.in:1050
+msgid ""
+"Tails will only connect to Tor after you configured Tor bridges. Bridges are secret Tor relays that hide that you are connecting to Tor.\n"
+"\n"
+"Our team is doing its best to help you connect to Tor using the most discrete types of Tor bridges.\n"
+"\n"
+"You will have to do extra configuration if you don't know any Tor bridges yet, if you connect from a public Wi-Fi network, or if you are in the Eastern Hemisphere."
+msgstr "Tails ne se connectera à Tor qu’une fois que vous aurez des ponts Tor. Les ponts sont des relais Tor secrets qui dissimulent le fait que vous vous connectez Tor. Notre équipe fait de son mieux pour vous aider à vous connecter à Tor grâce aux types de ponts Tor les plus discrets. Une configuration supplémentaire sera nécessaire si vous ne connaissez encore aucun pont Tor, si vous vous connectez d’un réseau Wi-Fi public, ou si vous vous trouvez dans l’hémisphère oriental."
+
+#: ../config/chroot_local-includes/usr/share/tails/tca/main.ui.in:1098
+msgid ""
+"<a href=\"doc/anonymous_internet/tor\">Learn more about how Tails connects "
+"to Tor</a>"
+msgstr "<a href=\"doc/anonymous_internet/tor\">En apprendre davantage sur la façon dont Tails se connecte à Tor</a>"
+
+#: ../config/chroot_local-includes/usr/share/tails/tca/main.ui.in:1184
+msgid "Connect to a local network"
+msgstr "Se connecter à un réseau local"
+
+#: ../config/chroot_local-includes/usr/share/tails/tca/main.ui.in:1201
+msgid ""
+"You are not connected to a local network yet. To be able to connect to the "
+"Tor network, you first need to connect to a Wi-Fi, wire, or mobile network."
+msgstr "Vous n’êtes pas encore connecté à un réseau local. Afin de vous connecter au réseau Tor, vous devez d’abord vous connecter à un réseau Wi-Fi, filaire ou mobile."
+
+#: ../config/chroot_local-includes/usr/share/tails/tca/main.ui.in:1213
+msgid "Open Wi-Fi settings"
+msgstr "Ouvrir les paramètres du Wi-Fi"
+
+#: ../config/chroot_local-includes/usr/share/tails/tca/main.ui.in:1262
+msgid "Testing Internet access…"
+msgstr "Test de l’accès à Internet…"
+
+#: ../config/chroot_local-includes/usr/share/tails/tca/main.ui.in:1302
+msgid "You have access to the Internet"
+msgstr "Vous avez accès à Internet"
+
+#: ../config/chroot_local-includes/usr/share/tails/tca/main.ui.in:1336
+msgid "Testing access to Tor…"
+msgstr "Test de l’accès à Tor…"
+
+#: ../config/chroot_local-includes/usr/share/tails/tca/main.ui.in:1379
+msgid "You can connect to Tor"
+msgstr "Vous pouvez vous connecter à Tor"
+
+#: ../config/chroot_local-includes/usr/share/tails/tca/main.ui.in:1409
+msgid "Failed to connect to Tor without bridges."
+msgstr "Échec de connexion à Tor sans pont."
+
+#: ../config/chroot_local-includes/usr/share/tails/tca/main.ui.in:1425
+msgid "Your local network is blocking access to Tor."
+msgstr "Votre réseau local bloque l’accès Tor."
+
+#: ../config/chroot_local-includes/usr/share/tails/tca/main.ui.in:1457
+msgid "Connecting to Tor…"
+msgstr "Connexion à Tor…"
+
+#: ../config/chroot_local-includes/usr/share/tails/tca/main.ui.in:1513
+msgid "Connected to Tor successfully"
+msgstr "Vous êtes connecté à Tor avec succès"
+
+#: ../config/chroot_local-includes/usr/share/tails/tca/main.ui.in:1537
+msgid "You can now browse the Internet anonymously and uncensored."
+msgstr "Vous pouvez désormais parcourir Internet anonymement et sans censure."
+
+#: ../config/chroot_local-includes/usr/share/tails/tca/main.ui.in:1578
+msgid "Open Network Monitor"
+msgstr "Ouvrir le moniteur du réseau"
+
+#: ../config/chroot_local-includes/usr/share/tails/tca/main.ui.in:1592
+msgid "View Tor Circuits"
+msgstr "Visualiser les circuits Tor"
+
+#: ../config/chroot_local-includes/usr/share/tails/tca/main.ui.in:1606
+msgid "Reset Tor Connection"
+msgstr "Réinitialiser la connexion à Tor"
+
+#: ../config/chroot_local-includes/usr/share/tails/tca/main.ui.in:1646
+msgid "Configure a Local Proxy"
+msgstr "Configurer un mandataire local"
+
+#: ../config/chroot_local-includes/usr/share/tails/tca/main.ui.in:1671
+msgid "Proxy Type"
+msgstr "Type de mandataire"
+
+#: ../config/chroot_local-includes/usr/share/tails/tca/main.ui.in:1685
+msgid "No proxy"
+msgstr "Aucun mandataire"
+
+#: ../config/chroot_local-includes/usr/share/tails/tca/main.ui.in:1686
+msgid "SOCKS 4"
+msgstr "SOCKS 4"
+
+#: ../config/chroot_local-includes/usr/share/tails/tca/main.ui.in:1687
+msgid "SOCKS 5"
+msgstr "SOCKS 5"
+
+#: ../config/chroot_local-includes/usr/share/tails/tca/main.ui.in:1688
+msgid "HTTP / HTTPS"
+msgstr "HTTP/HTTPS"
+
+#: ../config/chroot_local-includes/usr/share/tails/tca/main.ui.in:1704
+msgid "Address"
+msgstr "Adresse"
+
+#: ../config/chroot_local-includes/usr/share/tails/tca/main.ui.in:1718
+msgid "Username"
+msgstr "Nom d’utilisateur"
+
+#: ../config/chroot_local-includes/usr/share/tails/tca/main.ui.in:1732
+msgid "IP address or hostname"
+msgstr "Adresse IP ou nom d’hôte"
+
+#: ../config/chroot_local-includes/usr/share/tails/tca/main.ui.in:1747
+msgid "Port"
+msgstr "Port"
+
+#: ../config/chroot_local-includes/usr/share/tails/tca/main.ui.in:1841
+msgid "_Save Proxy Settings"
+msgstr "_Enregistrer les paramètres du mandataire"
1
0
[translation/tails-misc] https://gitweb.torproject.org/translation.git/commit/?h=tails-misc
by translation@torproject.org 02 Jul '21
by translation@torproject.org 02 Jul '21
02 Jul '21
commit 9c0846433a02d587c9d1d4573eb853fc6eb29b60
Author: Translation commit bot <translation(a)torproject.org>
Date: Fri Jul 2 16:15:38 2021 +0000
https://gitweb.torproject.org/translation.git/commit/?h=tails-misc
---
fr.po | 14 +++++++-------
he.po | 16 ++++++++--------
2 files changed, 15 insertions(+), 15 deletions(-)
diff --git a/fr.po b/fr.po
index 2428d764eb..ad7837f888 100644
--- a/fr.po
+++ b/fr.po
@@ -42,7 +42,7 @@ msgstr ""
"Project-Id-Version: Tor Project\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2021-07-01 11:43+0200\n"
-"PO-Revision-Date: 2021-07-02 15:42+0000\n"
+"PO-Revision-Date: 2021-07-02 16:03+0000\n"
"Last-Translator: AO <ao(a)localizationlab.org>\n"
"Language-Team: French (http://www.transifex.com/otf/torproject/language/fr/)\n"
"MIME-Version: 1.0\n"
@@ -1759,18 +1759,18 @@ msgstr "L’adresse du pont est malformée"
#: config/chroot_local-includes/usr/lib/python3/dist-packages/tca/ui/main_window.py:514
msgid "Setting a bridge is needed if you want to hide that you are using Tor"
-msgstr "La mise en place d'un pont est nécessaire si vous souhaitez cacher que vous utilisez Tor. "
+msgstr "Vous devez définir un pont si vous voulez dissimuler le fait que vous utilisez Tor."
#: config/chroot_local-includes/usr/lib/python3/dist-packages/tca/ui/main_window.py:777
msgid "Are you sure you want to lose progress?"
-msgstr "Êtes-vous sûr de vouloir perdre la progression ?"
+msgstr "Voulez-vous vraiment perdre la progression ?"
#: config/chroot_local-includes/usr/lib/python3/dist-packages/tca/ui/main_window.py:781
msgid ""
"Tails will continue connecting to Tor after you close the Tor Connection assistant.\n"
"\n"
"If connecting to Tor fails, you will have to wait again until the end of the progress bar to be able to troubleshoot your connection."
-msgstr "Tails continuera à se connecter à Tor après que vous ayez fermé l'assistant de Connexion à Tor.\n\nSi la connexion à Tor échoue, vous devrez à nouveau attendre la fin de la barre de progression pour pouvoir dépanner votre connexion."
+msgstr "Tails sera encore connecté à Tor une fois que vous aurez fermé l’assistant de connexion à Tor.\n\nSi la connexion à Tor échoue, vous devrez de nouveau attendre la fin de la barre de progression afin de dépanner votre connexion."
#: config/chroot_local-includes/usr/local/bin/thunderbird:41
msgid "You need to migrate your OpenPGP keys"
@@ -2371,7 +2371,7 @@ msgid ""
"A captive portal is a web page that is displayed before you can access the Internet. Captive portals usually require you to log in to the network or enter information such as an email address.\n"
"\n"
"The Unsafe Browser is not anonymous and can deanonymize you. Use it only to sign in to networks."
-msgstr "Le Navigateur non sécurisé permet de vous connecter à un réseau utilisant un portail captif.\n\nUn portail captif est une page web qui est affichée avant d'accéder à Internet. Les portails captifs nécessitent généralement de s'identifier ou de saisir des informations comme une adresse courriel.\n\nLe Navigateur non sécurisé n'est pas anonyme et peut vous désanonymiser. Utilisez le uniquement pour vous connecter à des réseaux."
+msgstr "Le Navigateur non sécurisé vous permet de vous connecter à un réseau grâce à un portail captif.\n\nUn portail captif est une page Web qui est affichée avant que vous puissiez accéder à Internet. Les portails captifs exigent habituellement que vous vous connectiez au réseau ou que vous saisissiez des renseignements tels qu’une adresse courriel.\n\nLe Navigateur non sécurisé n’est pas anonyme et peut divulguer votre identité. Ne l’utilisez que pour vous connecter à des réseaux."
#: ../config/chroot_local-includes/usr/share/tails/greeter/additional_settings.ui.in:574
msgid "Disable the Unsafe Browser (default)"
@@ -2657,7 +2657,7 @@ msgid ""
"1. Send an empty email to <tt>bridges(a)torproject.org</tt> from a Gmail or Riseup email address.\n"
"\n"
"2. Type below the bridges that you received by email."
-msgstr "Pour demander de nouveaux ponts Tor, vous pouvez également :\n\n1. Envoyer un courriel vide à <tt>bridges(a)torproject.org</tt> depuis une adresse courriel Gmail ou Riseup.\n\n2. Saisir ci-dessous les ponts que vous avez reçus par courriel."
+msgstr "Pour demander de nouveaux ponts Tor, vous pouvez aussi :\n\n1. Envoyer un courriel vide à <tt>bridges(a)torproject.org</tt> à partir d’une adresse courriel Gmail ou Riseup.\n\n2. Saisir ci-dessous les ponts que vous avez reçus par courriel."
#: ../config/chroot_local-includes/usr/share/tails/tca/main.ui.in:740
#: ../config/chroot_local-includes/usr/share/tails/tca/main.ui.in:1154
@@ -2694,7 +2694,7 @@ msgid ""
"Tor bridges are secret Tor relays. Use a bridge as your first Tor relay if connections to Tor are blocked, for example in some countries, by some public networks, or by some parental controls.\n"
"\n"
"Choose this option if you already know that you need bridges. Otherwise, Tails will autodetect whether you need bridges to connect to Tor from your local network."
-msgstr "Les ponts de Tor sont des relais Tor secrets. Utilisez un pont comme premier relais si la connexion à Tor est bloquée, par exemple dans certains pays ou sur certains réseaux publics, ou encore par des contrôles parentaux.\n\nChoisissez cette option si vous savez déjà que vous avez besoin de ponts. Autrement, Tails détectera automatiquement si vous en avez besoin pour vous connecter à Tor de votre réseau local."
+msgstr "Les ponts de Tor sont des relais Tor secrets. Utilisez un pont comme premier relais Tor si les connexions à Tor sont bloquées, par exemple dans certains pays, par certains réseaux publics, ou encore par des contrôles parentaux.\n\nChoisissez cette option si vous savez déjà que vous avez besoin de ponts. Autrement, Tails détectera automatiquement si vous en avez besoin pour vous connecter à Tor de votre réseau local."
#: ../config/chroot_local-includes/usr/share/tails/tca/main.ui.in:984
msgid "<b>Hide to my local network that I'm connecting to Tor (safer)</b>"
diff --git a/he.po b/he.po
index e3029b6840..fe34f8f697 100644
--- a/he.po
+++ b/he.po
@@ -19,7 +19,7 @@ msgstr ""
"Project-Id-Version: Tor Project\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2021-07-01 11:43+0200\n"
-"PO-Revision-Date: 2021-07-02 15:43+0000\n"
+"PO-Revision-Date: 2021-07-02 15:50+0000\n"
"Last-Translator: ION\n"
"Language-Team: Hebrew (http://www.transifex.com/otf/torproject/language/he/)\n"
"MIME-Version: 1.0\n"
@@ -1750,11 +1750,11 @@ msgstr ""
#: config/chroot_local-includes/usr/lib/python3/dist-packages/tca/ui/main_window.py:514
msgid "Setting a bridge is needed if you want to hide that you are using Tor"
-msgstr ""
+msgstr "הגדרת גשר דרושה אם אתה רוצה להסתיר שאתה משתמש ב־Tor"
#: config/chroot_local-includes/usr/lib/python3/dist-packages/tca/ui/main_window.py:777
msgid "Are you sure you want to lose progress?"
-msgstr ""
+msgstr "האם אתה בטוח שאתה רוצה לאבד התקדמות?"
#: config/chroot_local-includes/usr/lib/python3/dist-packages/tca/ui/main_window.py:781
msgid ""
@@ -2167,7 +2167,7 @@ msgstr "מפתח ציבורי OpenPGP בלתי תקף של איש קשר"
#: config/chroot_local-includes/usr/local/bin/tca:140
msgid "You turned on Offline Mode in the Welcome Screen."
-msgstr ""
+msgstr "הפעלת מצב לא מקוון במסך ברוך הבא."
#: config/chroot_local-includes/usr/local/bin/tca:141
msgid "It is impossible to connect to Tor in Offline Mode."
@@ -2176,7 +2176,7 @@ msgstr "זה בלתי אפשרי להתחבר אל Tor במצב לא מקוון.
#: config/chroot_local-includes/usr/local/bin/tca:142
msgid ""
"To connect to Tor and the Internet, restart Tails without Offline Mode."
-msgstr ""
+msgstr "כדי להתחבר אל Tor ואל האינטרנט, הפעל מחדש את Tails בלי מצב לא מקוון."
#: ../config/chroot_local-includes/etc/skel/Desktop/Report_an_error.desktop.in.h:1
msgid "Report an error"
@@ -2665,7 +2665,7 @@ msgstr "Tor מצפין ומעלים זהות של החיבור שלך ע״י ה
#: ../config/chroot_local-includes/usr/share/tails/tca/main.ui.in:793
msgid "<b>Connect to Tor automatically (easier)</b>"
-msgstr ""
+msgstr "<b>התחבר אל Tor באופן אוטומטי (קל יותר)</b>"
#: ../config/chroot_local-includes/usr/share/tails/tca/main.ui.in:841
msgid ""
@@ -2689,7 +2689,7 @@ msgstr ""
#: ../config/chroot_local-includes/usr/share/tails/tca/main.ui.in:984
msgid "<b>Hide to my local network that I'm connecting to Tor (safer)</b>"
-msgstr ""
+msgstr "<b>הסתר אל הרשת המקומית שלי שאני מתחבר אל Tor (בטוח יותר)</b>"
#: ../config/chroot_local-includes/usr/share/tails/tca/main.ui.in:1032
msgid ""
@@ -2720,7 +2720,7 @@ msgstr "התחבר אל רשת מקומית"
msgid ""
"You are not connected to a local network yet. To be able to connect to the "
"Tor network, you first need to connect to a Wi-Fi, wire, or mobile network."
-msgstr ""
+msgstr "אתה לא מחובר עדיין אל רשת מקומית. כדי להיות מסוגל להתחבר אל רשת Tor, אתה צריך תחילה להתחבר אל רשת Wi-Fi, רשת חוטית או רשת סלולרית."
#: ../config/chroot_local-includes/usr/share/tails/tca/main.ui.in:1213
msgid "Open Wi-Fi settings"
1
0
[Git][tpo/applications/android-components][android-components-90.0.11-10.5-1] 12 commits: Bug 40005: Modify Default toolbar menu
by Matthew Finkel (@sysrqb) 02 Jul '21
by Matthew Finkel (@sysrqb) 02 Jul '21
02 Jul '21
Matthew Finkel pushed to branch android-components-90.0.11-10.5-1 at The Tor Project / Applications / android-components
Commits:
f2d2d393 by Matthew Finkel at 2021-06-29T17:50:05+02:00
Bug 40005: Modify Default toolbar menu
- - - - -
62f1b1e7 by Alex Catarineu at 2021-06-29T17:54:36+02:00
Bug 40007: Port external helper app prompting
Together with the corresponding fenix patch, this allows all `startActivity`
that may open external apps to be replaced by `TorUtils.startActivityPrompt`.
- - - - -
d2e002c7 by Alex Catarineu at 2021-06-29T17:55:26+02:00
Bug 40002: Ensure system download manager is not used
- - - - -
4995507b by Alex Catarineu at 2021-06-29T17:55:28+02:00
Bug 40009: Change the default search engines
This matches the search engines from desktop, that is:
DDG as the default, then YouTube, Google, DDGOnion,
Startpage, Twitter, Wikipedia and Yahoo.
- - - - -
4ea637b9 by Alex Catarineu at 2021-06-29T17:55:29+02:00
Modify Addon support
Bug 40011: Hide option for disallowing addons in private mode
Bug 40016: Allow inheriting from AddonCollectionProvider
This will allow implementing our own AddonsProvider in fenix.
- - - - -
2e1052d2 by Georg Koppen at 2021-06-29T17:55:31+02:00
Bug 40013: Add option do overwrite timestamp in extension version
- - - - -
36c6ff30 by Alex Catarineu at 2021-06-29T17:55:33+02:00
Bug 40015: Port padlock states for .onion services
- - - - -
29d1079d by Alex Catarineu at 2021-06-29T17:55:35+02:00
Bug 40021: Force telemetry=false in Fennec settings migration
- - - - -
2a385862 by Alex Catarineu at 2021-06-29T17:55:37+02:00
Bug 40022: Migrate Tor security level from Fennec
- - - - -
2cc7d059 by Matthew Finkel at 2021-06-29T17:55:38+02:00
Modify Tracking Protection configuration
Bug 40020: Disable third-party cookies
Bug 40024: Disable tracking protection by default
- - - - -
fa4c99db by Matthew Finkel at 2021-06-29T17:55:40+02:00
Bug 40023: Stop PrivateNotificationService
- - - - -
0d763bf1 by Matthew Finkel at 2021-06-29T18:03:33+02:00
Add support for new GeckoView interfaces
Bug 40006: Expose Security Level interface
Bug 40019: Expose spoofEnglish pref
Bug 34439: Isolate Icon loader on Android
- - - - -
30 changed files:
- build.gradle
- components/browser/engine-gecko/src/main/java/mozilla/components/browser/engine/gecko/GeckoEngine.kt
- components/browser/engine-gecko/src/main/java/mozilla/components/browser/engine/gecko/fetch/GeckoViewFetchClient.kt
- components/browser/icons/src/main/java/mozilla/components/browser/icons/loader/HttpIconLoader.kt
- components/browser/menu/src/main/java/mozilla/components/browser/menu/WebExtensionBrowserMenuBuilder.kt
- + components/browser/search/src/main/assets/searchplugins/ddg-onion.xml
- + components/browser/search/src/main/assets/searchplugins/startpage.xml
- + components/browser/search/src/main/assets/searchplugins/yahoo.xml
- components/browser/toolbar/src/main/java/mozilla/components/browser/toolbar/display/DisplayToolbar.kt
- components/browser/toolbar/src/main/java/mozilla/components/browser/toolbar/display/SiteSecurityIconView.kt
- components/browser/toolbar/src/main/res/drawable/mozac_ic_site_security.xml
- components/browser/toolbar/src/main/res/values/attrs_browser_toolbar.xml
- components/concept/engine/src/main/java/mozilla/components/concept/engine/EngineSession.kt
- components/concept/engine/src/main/java/mozilla/components/concept/engine/Settings.kt
- components/concept/fetch/src/main/java/mozilla/components/concept/fetch/Request.kt
- components/concept/toolbar/src/main/java/mozilla/components/concept/toolbar/Toolbar.kt
- components/feature/addons/src/main/java/mozilla/components/feature/addons/amo/AddonCollectionProvider.kt
- components/feature/addons/src/main/res/layout/mozac_feature_addons_fragment_dialog_addon_installed.xml
- components/feature/app-links/build.gradle
- components/feature/app-links/src/main/java/mozilla/components/feature/app/links/AppLinksFeature.kt
- components/feature/app-links/src/main/java/mozilla/components/feature/app/links/AppLinksUseCases.kt
- components/feature/contextmenu/src/main/java/mozilla/components/feature/contextmenu/ContextMenuCandidate.kt
- components/feature/downloads/build.gradle
- components/feature/downloads/src/main/java/mozilla/components/feature/downloads/AbstractFetchDownloadService.kt
- components/feature/downloads/src/main/java/mozilla/components/feature/downloads/DownloadsFeature.kt
- components/feature/privatemode/src/main/java/mozilla/components/feature/privatemode/notification/PrivateNotificationFeature.kt
- components/feature/search/src/main/assets/search/list.json
- components/feature/search/src/main/assets/searchplugins/ddg.xml
- components/feature/toolbar/src/main/java/mozilla/components/feature/toolbar/ToolbarPresenter.kt
- components/support/ktx/src/main/java/mozilla/components/support/ktx/android/content/Context.kt
The diff was not included because it is too large.
View it on GitLab: https://gitlab.torproject.org/tpo/applications/android-components/-/compare…
--
View it on GitLab: https://gitlab.torproject.org/tpo/applications/android-components/-/compare…
You're receiving this email because of your account on gitlab.torproject.org.
1
0
[tor-browser/tor-browser-90.0b12-10.5-1] Bug 19121: reinstate the update.xml hash check
by sysrqb@torproject.org 02 Jul '21
by sysrqb@torproject.org 02 Jul '21
02 Jul '21
commit 4c10b04c49fe65e641c121893c8032792ae4ed51
Author: Kathy Brade <brade(a)pearlcrescent.com>
Date: Mon Apr 23 15:22:57 2018 -0400
Bug 19121: reinstate the update.xml hash check
Revert most changes from Mozilla Bug 1373267 "Remove hashFunction and
hashValue attributes from nsIUpdatePatch and code related to these
attributes." Changes to the tests were not reverted; the tests have
been changed significantly and we do not run automated updater tests
for Tor Browser at this time.
Also partial revert of commit f1241db6986e4b54473a1ed870f7584c75d51122.
Revert the nsUpdateService.js changes from Mozilla Bug 862173 "don't
verify mar file hash when using mar signing to verify the mar file
(lessens main thread I/O)."
Changes to the tests were not reverted; the tests have been changed
significantly and we do not run automated updater tests for
Tor Browser at this time.
We kept the addition to the AppConstants API in case other JS code
references it in the future.
---
toolkit/modules/AppConstants.jsm | 7 ++++
toolkit/mozapps/update/UpdateService.jsm | 63 ++++++++++++++++++++++++++++-
toolkit/mozapps/update/UpdateTelemetry.jsm | 1 +
toolkit/mozapps/update/nsIUpdateService.idl | 11 +++++
4 files changed, 81 insertions(+), 1 deletion(-)
diff --git a/toolkit/modules/AppConstants.jsm b/toolkit/modules/AppConstants.jsm
index 955f7952af11..59565b5af06c 100644
--- a/toolkit/modules/AppConstants.jsm
+++ b/toolkit/modules/AppConstants.jsm
@@ -205,6 +205,13 @@ this.AppConstants = Object.freeze({
false,
#endif
+ MOZ_VERIFY_MAR_SIGNATURE:
+#ifdef MOZ_VERIFY_MAR_SIGNATURE
+ true,
+#else
+ false,
+#endif
+
MOZ_MAINTENANCE_SERVICE:
#ifdef MOZ_MAINTENANCE_SERVICE
true,
diff --git a/toolkit/mozapps/update/UpdateService.jsm b/toolkit/mozapps/update/UpdateService.jsm
index 4d1b1c59eff5..10581c785074 100644
--- a/toolkit/mozapps/update/UpdateService.jsm
+++ b/toolkit/mozapps/update/UpdateService.jsm
@@ -969,6 +969,20 @@ function LOG(string) {
}
}
+/**
+ * Convert a string containing binary values to hex.
+ */
+function binaryToHex(input) {
+ var result = "";
+ for (var i = 0; i < input.length; ++i) {
+ var hex = input.charCodeAt(i).toString(16);
+ if (hex.length == 1)
+ hex = "0" + hex;
+ result += hex;
+ }
+ return result;
+}
+
/**
* Gets the specified directory at the specified hierarchy under the
* update root directory and creates it if it doesn't exist.
@@ -1988,6 +2002,8 @@ function UpdatePatch(patch) {
}
break;
case "finalURL":
+ case "hashFunction":
+ case "hashValue":
case "state":
case "type":
case "URL":
@@ -2007,6 +2023,8 @@ UpdatePatch.prototype = {
// over writing nsIUpdatePatch attributes.
_attrNames: [
"errorCode",
+ "hashFunction",
+ "hashValue",
"finalURL",
"selected",
"size",
@@ -2020,6 +2038,8 @@ UpdatePatch.prototype = {
*/
serialize: function UpdatePatch_serialize(updates) {
var patch = updates.createElementNS(URI_UPDATE_NS, "patch");
+ patch.setAttribute("hashFunction", this.hashFunction);
+ patch.setAttribute("hashValue", this.hashValue);
patch.setAttribute("size", this.size);
patch.setAttribute("type", this.type);
patch.setAttribute("URL", this.URL);
@@ -5122,7 +5142,42 @@ Downloader.prototype = {
}
LOG("Downloader:_verifyDownload downloaded size == expected size.");
- return true;
+ let fileStream = Cc["@mozilla.org/network/file-input-stream;1"].
+ createInstance(Ci.nsIFileInputStream);
+ fileStream.init(destination, FileUtils.MODE_RDONLY, FileUtils.PERMS_FILE, 0);
+
+ let digest;
+ try {
+ let hash = Cc["@mozilla.org/security/hash;1"].
+ createInstance(Ci.nsICryptoHash);
+ var hashFunction = Ci.nsICryptoHash[this._patch.hashFunction.toUpperCase()];
+ if (hashFunction == undefined) {
+ throw Cr.NS_ERROR_UNEXPECTED;
+ }
+ hash.init(hashFunction);
+ hash.updateFromStream(fileStream, -1);
+ // NOTE: For now, we assume that the format of _patch.hashValue is hex
+ // encoded binary (such as what is typically output by programs like
+ // sha1sum). In the future, this may change to base64 depending on how
+ // we choose to compute these hashes.
+ digest = binaryToHex(hash.finish(false));
+ } catch (e) {
+ LOG("Downloader:_verifyDownload - failed to compute hash of the " +
+ "downloaded update archive");
+ digest = "";
+ }
+
+ fileStream.close();
+
+ if (digest == this._patch.hashValue.toLowerCase()) {
+ LOG("Downloader:_verifyDownload hashes match.");
+ return true;
+ }
+
+ LOG("Downloader:_verifyDownload hashes do not match. ");
+ AUSTLMY.pingDownloadCode(this.isCompleteUpdate,
+ AUSTLMY.DWNLD_ERR_VERIFY_NO_HASH_MATCH);
+ return false;
},
/**
@@ -5719,6 +5774,9 @@ Downloader.prototype = {
" is higher than patch size: " +
this._patch.size
);
+ // It's important that we use a different code than
+ // NS_ERROR_CORRUPTED_CONTENT so that tests can verify the difference
+ // between a hash error and a wrong download error.
AUSTLMY.pingDownloadCode(
this.isCompleteUpdate,
AUSTLMY.DWNLD_ERR_PATCH_SIZE_LARGER
@@ -5737,6 +5795,9 @@ Downloader.prototype = {
" is not equal to expected patch size: " +
this._patch.size
);
+ // It's important that we use a different code than
+ // NS_ERROR_CORRUPTED_CONTENT so that tests can verify the difference
+ // between a hash error and a wrong download error.
AUSTLMY.pingDownloadCode(
this.isCompleteUpdate,
AUSTLMY.DWNLD_ERR_PATCH_SIZE_NOT_EQUAL
diff --git a/toolkit/mozapps/update/UpdateTelemetry.jsm b/toolkit/mozapps/update/UpdateTelemetry.jsm
index dae76e09acd0..df5b8917970e 100644
--- a/toolkit/mozapps/update/UpdateTelemetry.jsm
+++ b/toolkit/mozapps/update/UpdateTelemetry.jsm
@@ -192,6 +192,7 @@ var AUSTLMY = {
DWNLD_ERR_VERIFY_NO_REQUEST: 13,
DWNLD_ERR_VERIFY_PATCH_SIZE_NOT_EQUAL: 14,
DWNLD_ERR_WRITE_FAILURE: 15,
+ DWNLD_ERR_VERIFY_NO_HASH_MATCH: 16,
// Temporary failure code to see if there are failures without an update phase
DWNLD_UNKNOWN_PHASE_ERR_WRITE_FAILURE: 40,
diff --git a/toolkit/mozapps/update/nsIUpdateService.idl b/toolkit/mozapps/update/nsIUpdateService.idl
index 78929e1cef44..5db1db71fc81 100644
--- a/toolkit/mozapps/update/nsIUpdateService.idl
+++ b/toolkit/mozapps/update/nsIUpdateService.idl
@@ -39,6 +39,17 @@ interface nsIUpdatePatch : nsISupports
*/
attribute AString finalURL;
+ /**
+ * The hash function to use when determining this file's integrity
+ */
+ attribute AString hashFunction;
+
+ /**
+ * The value of the hash function named above that should be computed if
+ * this file is not corrupt.
+ */
+ attribute AString hashValue;
+
/**
* The size of this file, in bytes.
*/
1
0
[tor-browser/tor-browser-90.0b12-10.5-1] Bug 13379: Sign our MAR files.
by sysrqb@torproject.org 02 Jul '21
by sysrqb@torproject.org 02 Jul '21
02 Jul '21
commit 6901adebc0feb7f13dd642384fefd4bbbf228a8c
Author: Kathy Brade <brade(a)pearlcrescent.com>
Date: Wed Dec 17 16:37:11 2014 -0500
Bug 13379: Sign our MAR files.
Configure with --enable-verify-mar (when updating, require a valid
signature on the MAR file before it is applied).
Use the Tor Browser version instead of the Firefox version inside the
MAR file info block (necessary to prevent downgrade attacks).
Use NSS on all platforms for checking MAR signatures (instead of using
OS-native APIs, which Mozilla does on Mac OS and Windows). So that the
NSS and NSPR libraries the updater depends on can be found at runtime,
we add the firefox directory to the shared library search path on macOS.
On Linux, rpath is used by Mozilla to solve that problem, but that
approach won't work on macOS because the updater executable is copied
during the update process to a location that is under TorBrowser-Data,
and the location of TorBrowser-Data varies.
Also includes the fix for bug 18900.
---
.mozconfig | 1 +
.mozconfig-asan | 1 +
.mozconfig-mac | 1 +
.mozconfig-mingw | 1 +
modules/libmar/tool/mar.c | 6 +--
modules/libmar/tool/moz.build | 12 ++++--
modules/libmar/verify/moz.build | 14 +++---
.../mozapps/update/updater/updater-common.build | 26 +++++++++--
toolkit/mozapps/update/updater/updater.cpp | 25 +++++++----
toolkit/xre/moz.build | 3 ++
toolkit/xre/nsUpdateDriver.cpp | 50 ++++++++++++++++++++++
11 files changed, 115 insertions(+), 25 deletions(-)
diff --git a/.mozconfig b/.mozconfig
index 18cd1f9b6487..c50c57d410de 100755
--- a/.mozconfig
+++ b/.mozconfig
@@ -37,3 +37,4 @@ ac_add_options MOZ_TELEMETRY_REPORTING=
ac_add_options --disable-tor-launcher
ac_add_options --with-tor-browser-version=dev-build
ac_add_options --disable-tor-browser-update
+ac_add_options --enable-verify-mar
diff --git a/.mozconfig-asan b/.mozconfig-asan
index bad7ea022c9f..e42ff6c86bc5 100644
--- a/.mozconfig-asan
+++ b/.mozconfig-asan
@@ -29,6 +29,7 @@ ac_add_options --enable-official-branding
ac_add_options --enable-default-toolkit=cairo-gtk3
ac_add_options --enable-tor-browser-update
+ac_add_options --enable-verify-mar
ac_add_options --disable-strip
ac_add_options --disable-install-strip
diff --git a/.mozconfig-mac b/.mozconfig-mac
index 26e2b6b92fdb..5b4624ef1f67 100644
--- a/.mozconfig-mac
+++ b/.mozconfig-mac
@@ -43,6 +43,7 @@ ac_add_options --disable-debug
ac_add_options --enable-tor-browser-data-outside-app-dir
ac_add_options --enable-tor-browser-update
+ac_add_options --enable-verify-mar
ac_add_options --disable-crashreporter
ac_add_options --disable-webrtc
diff --git a/.mozconfig-mingw b/.mozconfig-mingw
index 3ec6ff18a3e9..ce6ace1dad67 100644
--- a/.mozconfig-mingw
+++ b/.mozconfig-mingw
@@ -15,6 +15,7 @@ ac_add_options --enable-strip
ac_add_options --enable-official-branding
ac_add_options --enable-tor-browser-update
+ac_add_options --enable-verify-mar
ac_add_options --disable-bits-download
# Let's make sure no preference is enabling either Adobe's or Google's CDM.
diff --git a/modules/libmar/tool/mar.c b/modules/libmar/tool/mar.c
index 0bf2cb4bd1d4..ea2b79924914 100644
--- a/modules/libmar/tool/mar.c
+++ b/modules/libmar/tool/mar.c
@@ -65,7 +65,7 @@ static void print_usage() {
"signed_input_archive.mar base_64_encoded_signature_file "
"changed_signed_output.mar\n");
printf("(i) is the index of the certificate to extract\n");
-# if defined(XP_MACOSX) || (defined(XP_WIN) && !defined(MAR_NSS))
+# if (defined(XP_MACOSX) || defined(XP_WIN)) && !defined(MAR_NSS)
printf("Verify a MAR file:\n");
printf(" mar [-C workingDir] -D DERFilePath -v signed_archive.mar\n");
printf(
@@ -149,7 +149,7 @@ int main(int argc, char** argv) {
memset((void*)certBuffers, 0, sizeof(certBuffers));
#endif
#if !defined(NO_SIGN_VERIFY) && \
- ((!defined(MAR_NSS) && defined(XP_WIN)) || defined(XP_MACOSX))
+ (!defined(MAR_NSS) && (defined(XP_WIN) || defined(XP_MACOSX)))
memset(DERFilePaths, 0, sizeof(DERFilePaths));
memset(fileSizes, 0, sizeof(fileSizes));
#endif
@@ -181,7 +181,7 @@ int main(int argc, char** argv) {
argc -= 2;
}
#if !defined(NO_SIGN_VERIFY)
-# if (!defined(MAR_NSS) && defined(XP_WIN)) || defined(XP_MACOSX)
+# if (!defined(MAR_NSS) && (defined(XP_WIN) || defined(XP_MACOSX)))
/* -D DERFilePath, also matches -D[index] DERFilePath
We allow an index for verifying to be symmetric
with the import and export command line arguments. */
diff --git a/modules/libmar/tool/moz.build b/modules/libmar/tool/moz.build
index a6d26c66a668..d6fa1677ddf1 100644
--- a/modules/libmar/tool/moz.build
+++ b/modules/libmar/tool/moz.build
@@ -43,15 +43,21 @@ if CONFIG["MOZ_BUILD_APP"] != "tools/update-packaging":
"verifymar",
]
+ if CONFIG["TOR_BROWSER_UPDATE"]:
+ DEFINES["MAR_NSS"] = True
+
if CONFIG["OS_ARCH"] == "WINNT":
USE_STATIC_LIBS = True
OS_LIBS += [
"ws2_32",
- "crypt32",
- "advapi32",
]
- elif CONFIG["OS_ARCH"] == "Darwin":
+ if not CONFIG["TOR_BROWSER_UPDATE"]:
+ OS_LIBS += [
+ "crypt32",
+ "advapi32",
+ ]
+ elif CONFIG["OS_ARCH"] == "Darwin" and not CONFIG["TOR_BROWSER_UPDATE"]:
OS_LIBS += [
"-framework Security",
]
diff --git a/modules/libmar/verify/moz.build b/modules/libmar/verify/moz.build
index b07475655f0d..03718eee50b4 100644
--- a/modules/libmar/verify/moz.build
+++ b/modules/libmar/verify/moz.build
@@ -16,15 +16,12 @@ FORCE_STATIC_LIB = True
if CONFIG["OS_ARCH"] == "WINNT":
USE_STATIC_LIBS = True
elif CONFIG["OS_ARCH"] == "Darwin":
- UNIFIED_SOURCES += [
- "MacVerifyCrypto.cpp",
- ]
- OS_LIBS += [
- "-framework Security",
+ USE_LIBS += [
+ "nspr",
+ "nss",
+ "signmar",
]
else:
- DEFINES["MAR_NSS"] = True
- LOCAL_INCLUDES += ["../sign"]
USE_LIBS += [
"nspr",
"nss",
@@ -38,6 +35,9 @@ else:
"-Wl,-rpath=\\$$ORIGIN",
]
+DEFINES["MAR_NSS"] = True
+LOCAL_INCLUDES += ["../sign"]
+
LOCAL_INCLUDES += [
"../src",
]
diff --git a/toolkit/mozapps/update/updater/updater-common.build b/toolkit/mozapps/update/updater/updater-common.build
index 13926ea82046..c9ef02bbe291 100644
--- a/toolkit/mozapps/update/updater/updater-common.build
+++ b/toolkit/mozapps/update/updater/updater-common.build
@@ -4,6 +4,12 @@
# 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/.
+DEFINES["MAR_NSS"] = True
+
+link_with_nss = DEFINES["MAR_NSS"] or (
+ CONFIG["OS_ARCH"] == "Linux" and CONFIG["MOZ_VERIFY_MAR_SIGNATURE"]
+)
+
srcs = [
"archivereader.cpp",
"updater.cpp",
@@ -36,10 +42,14 @@ if CONFIG["OS_ARCH"] == "WINNT":
"ws2_32",
"shell32",
"shlwapi",
- "crypt32",
- "advapi32",
]
+ if not link_with_nss:
+ OS_LIBS += [
+ "crypt32",
+ "advapi32",
+ ]
+
USE_LIBS += [
"bspatch",
"mar",
@@ -47,6 +57,13 @@ USE_LIBS += [
"xz-embedded",
]
+if link_with_nss:
+ USE_LIBS += [
+ "nspr",
+ "nss",
+ "signmar",
+ ]
+
if CONFIG["MOZ_WIDGET_TOOLKIT"] == "gtk":
have_progressui = 1
srcs += [
@@ -61,9 +78,12 @@ if CONFIG["MOZ_WIDGET_TOOLKIT"] == "cocoa":
]
OS_LIBS += [
"-framework Cocoa",
- "-framework Security",
"-framework SystemConfiguration",
]
+ if not link_with_nss:
+ OS_LIBS += [
+ "-framework Security",
+ ]
UNIFIED_SOURCES += [
"/toolkit/xre/updaterfileutils_osx.mm",
]
diff --git a/toolkit/mozapps/update/updater/updater.cpp b/toolkit/mozapps/update/updater/updater.cpp
index d22233066157..ddbcdf5cc22a 100644
--- a/toolkit/mozapps/update/updater/updater.cpp
+++ b/toolkit/mozapps/update/updater/updater.cpp
@@ -110,9 +110,11 @@ struct UpdateServerThreadArgs {
# define stat64 stat
#endif
-#if defined(MOZ_VERIFY_MAR_SIGNATURE) && !defined(XP_WIN) && !defined(XP_MACOSX)
-# include "nss.h"
-# include "prerror.h"
+#if defined(MOZ_VERIFY_MAR_SIGNATURE)
+# if defined(MAR_NSS) || (!defined(XP_WIN) && !defined(XP_MACOSX))
+# include "nss.h"
+# include "prerror.h"
+# endif
#endif
#include "crctable.h"
@@ -2732,8 +2734,13 @@ static void UpdateThreadFunc(void* param) {
if (ReadMARChannelIDs(updateSettingsPath, &MARStrings) != OK) {
rv = UPDATE_SETTINGS_FILE_CHANNEL;
} else {
+# ifdef TOR_BROWSER_UPDATE
+ const char* appVersion = TOR_BROWSER_VERSION_QUOTED;
+# else
+ const char* appVersion = MOZ_APP_VERSION;
+# endif
rv = gArchiveReader.VerifyProductInformation(
- MARStrings.MARChannelID.get(), MOZ_APP_VERSION);
+ MARStrings.MARChannelID.get(), appVersion);
}
}
}
@@ -2963,11 +2970,10 @@ int NS_main(int argc, NS_tchar** argv) {
}
#endif
-#if defined(MOZ_VERIFY_MAR_SIGNATURE) && !defined(XP_WIN) && !defined(XP_MACOSX)
- // On Windows and Mac we rely on native APIs to do verifications so we don't
- // need to initialize NSS at all there.
- // Otherwise, minimize the amount of NSS we depend on by avoiding all the NSS
- // databases.
+#if defined(MOZ_VERIFY_MAR_SIGNATURE)
+# if defined(MAR_NSS) || (!defined(XP_WIN) && !defined(XP_MACOSX))
+ // If using NSS for signature verification, initialize NSS but minimize
+ // the portion we depend on by avoiding all of the NSS databases.
if (NSS_NoDB_Init(nullptr) != SECSuccess) {
PRErrorCode error = PR_GetError();
fprintf(stderr, "Could not initialize NSS: %s (%d)", PR_ErrorToName(error),
@@ -2975,6 +2981,7 @@ int NS_main(int argc, NS_tchar** argv) {
_exit(1);
}
#endif
+#endif
#ifdef XP_MACOSX
if (!isElevated) {
diff --git a/toolkit/xre/moz.build b/toolkit/xre/moz.build
index 90d06481ee9e..53883cbf196f 100644
--- a/toolkit/xre/moz.build
+++ b/toolkit/xre/moz.build
@@ -233,6 +233,9 @@ for var in ("APP_VERSION", "APP_ID"):
if CONFIG["MOZ_BUILD_APP"] == "browser":
DEFINES["MOZ_BUILD_APP_IS_BROWSER"] = True
+if CONFIG["TOR_BROWSER_UPDATE"]:
+ DEFINES["MAR_NSS"] = True
+
LOCAL_INCLUDES += [
"../../other-licenses/nsis/Contrib/CityHash/cityhash",
"../components/find",
diff --git a/toolkit/xre/nsUpdateDriver.cpp b/toolkit/xre/nsUpdateDriver.cpp
index f83f28288786..4d2ca85928a9 100644
--- a/toolkit/xre/nsUpdateDriver.cpp
+++ b/toolkit/xre/nsUpdateDriver.cpp
@@ -366,6 +366,42 @@ static nsresult GetUpdateDirFromAppDir(nsIFile* aAppDir, nsIFile** aResult) {
# endif
#endif
+#if defined(TOR_BROWSER_UPDATE) && defined(MOZ_VERIFY_MAR_SIGNATURE) && \
+ defined(MAR_NSS) && defined(XP_MACOSX)
+/**
+ * Ideally we would save and restore the original library path value after
+ * the updater finishes its work (and before firefox is re-launched).
+ * Doing so would avoid potential problems like the following bug:
+ * https://bugzilla.mozilla.org/show_bug.cgi?id=1434033
+ */
+/**
+ * Appends the specified path to the library path.
+ * This is used so that the updater can find libnss3.dylib and other
+ * shared libs.
+ *
+ * @param pathToAppend A new library path to prepend to the dynamic linker's
+ * search path.
+ */
+# include "prprf.h"
+# define PATH_SEPARATOR ":"
+# define LD_LIBRARY_PATH_ENVVAR_NAME "DYLD_LIBRARY_PATH"
+static void AppendToLibPath(const char* pathToAppend) {
+ char* pathValue = getenv(LD_LIBRARY_PATH_ENVVAR_NAME);
+ if (nullptr == pathValue || '\0' == *pathValue) {
+ // Leak the string because that is required by PR_SetEnv.
+ char* s =
+ Smprintf("%s=%s", LD_LIBRARY_PATH_ENVVAR_NAME, pathToAppend).release();
+ PR_SetEnv(s);
+ } else {
+ // Leak the string because that is required by PR_SetEnv.
+ char* s = Smprintf("%s=%s" PATH_SEPARATOR "%s", LD_LIBRARY_PATH_ENVVAR_NAME,
+ pathToAppend, pathValue)
+ .release();
+ PR_SetEnv(s);
+ }
+}
+#endif
+
/**
* Applies, switches, or stages an update.
*
@@ -612,6 +648,20 @@ static void ApplyUpdate(nsIFile* greDir, nsIFile* updateDir, nsIFile* appDir,
PR_SetEnv("MOZ_SAFE_MODE_RESTART=1");
}
+#if defined(TOR_BROWSER_UPDATE) && defined(MOZ_VERIFY_MAR_SIGNATURE) && \
+ defined(MAR_NSS) && defined(XP_MACOSX)
+ // On macOS, append the app directory to the shared library search path
+ // so the system can locate the shared libraries that are needed by the
+ // updater, e.g., libnss3.dylib).
+ nsAutoCString appPath;
+ nsresult rv2 = appDir->GetNativePath(appPath);
+ if (NS_SUCCEEDED(rv2)) {
+ AppendToLibPath(appPath.get());
+ } else {
+ LOG(("ApplyUpdate -- appDir->GetNativePath() failed (0x%x)\n", rv2));
+ }
+#endif
+
LOG(("spawning updater process [%s]\n", updaterPath.get()));
#ifdef DEBUG
dump_argv("ApplyUpdate updater", argv, argc);
1
0
[tor-browser/tor-browser-90.0b12-10.5-1] Bug 21431: Clean-up system extensions shipped in Firefox
by sysrqb@torproject.org 02 Jul '21
by sysrqb@torproject.org 02 Jul '21
02 Jul '21
commit 84c3c16988aa70188d68fdb010d8d0fda16ce7ea
Author: Kathy Brade <brade(a)pearlcrescent.com>
Date: Tue May 23 17:05:29 2017 -0400
Bug 21431: Clean-up system extensions shipped in Firefox
Only ship the pdfjs extension.
---
browser/components/BrowserGlue.jsm | 6 ++++++
browser/extensions/moz.build | 9 +--------
browser/installer/package-manifest.in | 1 -
browser/locales/Makefile.in | 8 --------
browser/locales/jar.mn | 7 -------
5 files changed, 7 insertions(+), 24 deletions(-)
diff --git a/browser/components/BrowserGlue.jsm b/browser/components/BrowserGlue.jsm
index 5085128b4133..3dcd18d9b173 100644
--- a/browser/components/BrowserGlue.jsm
+++ b/browser/components/BrowserGlue.jsm
@@ -1967,6 +1967,9 @@ BrowserGlue.prototype = {
const ID = "screenshots(a)mozilla.org";
const _checkScreenshotsPref = async () => {
let addon = await AddonManager.getAddonByID(ID);
+ if (!addon) {
+ return;
+ }
let disabled = Services.prefs.getBoolPref(PREF, false);
if (disabled) {
await addon.disable({ allowSystemAddons: true });
@@ -1983,6 +1986,9 @@ BrowserGlue.prototype = {
const ID = "webcompat-reporter(a)mozilla.org";
Services.prefs.addObserver(PREF, async () => {
let addon = await AddonManager.getAddonByID(ID);
+ if (!addon) {
+ return;
+ }
let enabled = Services.prefs.getBoolPref(PREF, false);
if (enabled && !addon.isActive) {
await addon.enable({ allowSystemAddons: true });
diff --git a/browser/extensions/moz.build b/browser/extensions/moz.build
index fa60184daea8..72a9c9e9a636 100644
--- a/browser/extensions/moz.build
+++ b/browser/extensions/moz.build
@@ -4,14 +4,7 @@
# 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/.
-DIRS += [
- "doh-rollout",
- "formautofill",
- "screenshots",
- "webcompat",
- "report-site-issue",
- "pictureinpicture",
-]
+DIRS += []
if CONFIG["NIGHTLY_BUILD"]:
DIRS += [
diff --git a/browser/installer/package-manifest.in b/browser/installer/package-manifest.in
index 3644585d7c56..b3842ae863c6 100644
--- a/browser/installer/package-manifest.in
+++ b/browser/installer/package-manifest.in
@@ -267,7 +267,6 @@
@RESPATH@/browser/chrome/icons/default/default64.png
@RESPATH@/browser/chrome/icons/default/default128.png
#endif
-@RESPATH@/browser/features/*
; [DevTools Startup Files]
@RESPATH@/browser/chrome/devtools-startup@JAREXT@
diff --git a/browser/locales/Makefile.in b/browser/locales/Makefile.in
index 496379c4306f..0946188813da 100644
--- a/browser/locales/Makefile.in
+++ b/browser/locales/Makefile.in
@@ -58,10 +58,6 @@ l10n-%:
@$(MAKE) -C ../../toolkit/locales l10n-$* XPI_ROOT_APPID='$(XPI_ROOT_APPID)'
@$(MAKE) -C ../../services/sync/locales AB_CD=$* XPI_NAME=locale-$*
@$(MAKE) -C ../../extensions/spellcheck/locales AB_CD=$* XPI_NAME=locale-$*
-ifneq (,$(wildcard ../extensions/formautofill/locales))
- @$(MAKE) -C ../extensions/formautofill/locales AB_CD=$* XPI_NAME=locale-$*
-endif
- @$(MAKE) -C ../extensions/report-site-issue/locales AB_CD=$* XPI_NAME=locale-$*
@$(MAKE) -C ../../devtools/client/locales AB_CD=$* XPI_NAME=locale-$* XPI_ROOT_APPID='$(XPI_ROOT_APPID)'
@$(MAKE) -C ../../devtools/startup/locales AB_CD=$* XPI_NAME=locale-$* XPI_ROOT_APPID='$(XPI_ROOT_APPID)'
@$(MAKE) l10n AB_CD=$* XPI_NAME=locale-$* PREF_DIR=$(PREF_DIR)
@@ -75,14 +71,10 @@ chrome-%:
@$(MAKE) -C ../../toolkit/locales chrome-$*
@$(MAKE) -C ../../services/sync/locales chrome AB_CD=$*
@$(MAKE) -C ../../extensions/spellcheck/locales chrome AB_CD=$*
-ifneq (,$(wildcard ../extensions/formautofill/locales))
- @$(MAKE) -C ../extensions/formautofill/locales chrome AB_CD=$*
-endif
@$(MAKE) -C ../../devtools/client/locales chrome AB_CD=$*
@$(MAKE) -C ../../devtools/startup/locales chrome AB_CD=$*
@$(MAKE) chrome AB_CD=$*
@$(MAKE) -C $(DEPTH)/$(MOZ_BRANDING_DIRECTORY)/locales chrome AB_CD=$*
- @$(MAKE) -C ../extensions/report-site-issue/locales chrome AB_CD=$*
package-win32-installer: $(SUBMAKEFILES)
$(MAKE) -C ../installer/windows CONFIG_DIR=l10ngen ZIP_IN='$(ZIP_OUT)' installer
diff --git a/browser/locales/jar.mn b/browser/locales/jar.mn
index 7ba213f1b269..dc4ef79af6fa 100644
--- a/browser/locales/jar.mn
+++ b/browser/locales/jar.mn
@@ -50,10 +50,3 @@
locale/browser/netError.dtd (%chrome/overrides/netError.dtd)
locale/browser/appstrings.properties (%chrome/overrides/appstrings.properties)
locale/browser/fxmonitor.properties (%chrome/browser/fxmonitor.properties)
-
-#ifdef XPI_NAME
-# Bug 1240628, restructure how l10n repacks work with feature addons
-# This is hacky, but ensures the chrome.manifest chain is complete
-[.] chrome.jar:
-% manifest features/chrome.manifest
-#endif
1
0
[tor-browser/tor-browser-90.0b12-10.5-1] Bug 16285: Exclude ClearKey system for now
by sysrqb@torproject.org 02 Jul '21
by sysrqb@torproject.org 02 Jul '21
02 Jul '21
commit 7c49c8a2ae8a334d909efb71637e79bf52c7c68c
Author: Georg Koppen <gk(a)torproject.org>
Date: Mon May 22 12:44:40 2017 +0000
Bug 16285: Exclude ClearKey system for now
In the past the ClearKey system had not been compiled when specifying
--disable-eme. But that changed and it is even bundled nowadays (see:
Mozilla's bug 1300654). We don't want to ship it right now as the use
case for it is not really visible while the code had security
vulnerabilities in the past.
---
browser/installer/package-manifest.in | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/browser/installer/package-manifest.in b/browser/installer/package-manifest.in
index f0a60080cc39..3644585d7c56 100644
--- a/browser/installer/package-manifest.in
+++ b/browser/installer/package-manifest.in
@@ -467,8 +467,8 @@ bin/libfreebl_64int_3.so
#endif
; media
-@RESPATH@/gmp-clearkey/0.1/@DLL_PREFIX@clearkey@DLL_SUFFIX@
-@RESPATH@/gmp-clearkey/0.1/manifest.json
+;@RESPATH@/gmp-clearkey/0.1/@DLL_PREFIX@clearkey@DLL_SUFFIX@
+;@RESPATH@/gmp-clearkey/0.1/manifest.json
#ifdef MOZ_DMD
; DMD
1
0
[tor-browser/tor-browser-90.0b12-10.5-1] Bug 4234: Use the Firefox Update Process for Tor Browser.
by sysrqb@torproject.org 02 Jul '21
by sysrqb@torproject.org 02 Jul '21
02 Jul '21
commit f17f6589a1d7f65021343088bd0c858cd68f8733
Author: Kathy Brade <brade(a)pearlcrescent.com>
Date: Fri Jan 13 11:40:24 2017 -0500
Bug 4234: Use the Firefox Update Process for Tor Browser.
The following files are never updated:
TorBrowser/Data/Browser/profiles.ini
TorBrowser/Data/Browser/profile.default/bookmarks.html
TorBrowser/Data/Tor/torrc
Mac OS: Store update metadata under TorBrowser/UpdateInfo.
Removed the %OS_VERSION% component from the update URL (13047) and
added support for minSupportedOSVersion, an attribute of the
<update> element that may be used to trigger Firefox's
"unsupported platform" behavior.
Hide the "What's new" links (set app.releaseNotesURL value to about:blank).
Windows: disable "runas" code path in updater (15201).
Windows: avoid writing to the registry (16236).
Also includes fixes for tickets 13047, 13301, 13356, 13594, 15406,
16014, 16909, 24476, and 25909.
Also fix Bug 26049: reduce the delay before the update prompt is displayed.
Instead of Firefox's 2 days, we use 1 hour (after which time the update
doorhanger will be displayed).
Also fix bug 27221: purge the startup cache if the Tor Browser
version changed (even if the Firefox version and build ID did
not change), e.g., after a minor Tor Browser update.
Also fix 32616: Disable GetSecureOutputDirectoryPath() functionality.
Bug 26048: potentially confusing "restart to update" message
Within the update doorhanger, remove the misleading message that mentions
that windows will be restored after an update is applied, and replace the
"Restart and Restore" button label with an existing
"Restart to update Tor Browser" string.
Bug 28885: notify users that update is downloading
Add a "Downloading Tor Browser update" item which appears in the
hamburger (app) menu while the update service is downloading a MAR
file. Before this change, the browser did not indicate to the user
that an update was in progress, which is especially confusing in
Tor Browser because downloads often take some time. If the user
clicks on the new menu item, the about dialog is opened to allow
the user to see download progress.
As part of this fix, the update service was changed to always show
update-related messages in the hamburger menu, even if the update
was started in the foreground via the about dialog or via the
"Check for Tor Browser Update" toolbar menu item. This change is
consistent with the Tor Browser goal of making sure users are
informed about the update process.
Removed #28885 parts of this patch which have been uplifted to Firefox.
---
browser/app/Makefile.in | 2 +
browser/app/profile/000-tor-browser.js | 16 +-
browser/app/profile/firefox.js | 10 +-
browser/base/content/aboutDialog-appUpdater.js | 2 +-
browser/base/content/aboutDialog.js | 12 +-
browser/components/BrowserContentHandler.jsm | 39 ++-
.../customizableui/content/panelUI.inc.xhtml | 5 +-
browser/confvars.sh | 35 +--
browser/installer/package-manifest.in | 2 +
build/application.ini.in | 2 +-
build/moz.configure/init.configure | 3 +-
config/createprecomplete.py | 19 +-
.../client/aboutdebugging/src/actions/runtimes.js | 5 +
toolkit/modules/UpdateUtils.jsm | 22 +-
toolkit/mozapps/extensions/AddonManager.jsm | 24 ++
toolkit/mozapps/extensions/test/browser/head.js | 1 +
.../extensions/test/xpcshell/head_addons.js | 1 +
toolkit/mozapps/update/UpdateService.jsm | 125 +++++++-
toolkit/mozapps/update/UpdateServiceStub.jsm | 4 +
toolkit/mozapps/update/common/updatehelper.cpp | 8 +
toolkit/mozapps/update/moz.build | 5 +-
toolkit/mozapps/update/updater/launchchild_osx.mm | 2 +
toolkit/mozapps/update/updater/moz.build | 2 +-
toolkit/mozapps/update/updater/updater.cpp | 339 ++++++++++++++++++---
toolkit/xre/MacLaunchHelper.h | 2 +
toolkit/xre/MacLaunchHelper.mm | 2 +
toolkit/xre/nsAppRunner.cpp | 22 +-
toolkit/xre/nsUpdateDriver.cpp | 109 ++++++-
toolkit/xre/nsXREDirProvider.cpp | 42 ++-
tools/update-packaging/common.sh | 64 ++--
tools/update-packaging/make_full_update.sh | 25 ++
tools/update-packaging/make_incremental_update.sh | 71 ++++-
32 files changed, 877 insertions(+), 145 deletions(-)
diff --git a/browser/app/Makefile.in b/browser/app/Makefile.in
index 8dd3a9a65661..3a5550c96c15 100644
--- a/browser/app/Makefile.in
+++ b/browser/app/Makefile.in
@@ -97,10 +97,12 @@ tools repackage:: $(DIST)/bin/$(MOZ_APP_NAME) $(objdir)/macbuild/Contents/MacOS-
rsync -aL $(DIST)/bin/$(MOZ_APP_NAME) '$(dist_dest)/Contents/MacOS'
cp -RL $(topsrcdir)/$(MOZ_BRANDING_DIRECTORY)/firefox.icns '$(dist_dest)/Contents/Resources/firefox.icns'
cp -RL $(topsrcdir)/$(MOZ_BRANDING_DIRECTORY)/document.icns '$(dist_dest)/Contents/Resources/document.icns'
+ifndef TOR_BROWSER_UPDATE
$(MKDIR) -p '$(dist_dest)/Contents/Library/LaunchServices'
ifdef MOZ_UPDATER
mv -f '$(dist_dest)/Contents/MacOS/updater.app/Contents/MacOS/org.mozilla.updater' '$(dist_dest)/Contents/Library/LaunchServices'
ln -s ../../../../Library/LaunchServices/org.mozilla.updater '$(dist_dest)/Contents/MacOS/updater.app/Contents/MacOS/org.mozilla.updater'
+endif
endif
printf APPLTORB > '$(dist_dest)/Contents/PkgInfo'
endif
diff --git a/browser/app/profile/000-tor-browser.js b/browser/app/profile/000-tor-browser.js
index 0ae4d896ee7c..68caacc88b82 100644
--- a/browser/app/profile/000-tor-browser.js
+++ b/browser/app/profile/000-tor-browser.js
@@ -7,7 +7,6 @@
// Disable initial homepage notifications
pref("browser.search.update", false);
pref("browser.rights.3.shown", true);
-pref("browser.startup.homepage_override.mstone", "ignore");
pref("startup.homepage_welcome_url", "");
pref("startup.homepage_welcome_url.additional", "");
@@ -20,9 +19,17 @@ pref("startup.homepage_override_url", "https://blog.torproject.org/category/tags
// Try to nag a bit more about updates: Pop up a restart dialog an hour after the initial dialog
pref("app.update.promptWaitTime", 3600);
-
-#ifdef XP_WIN
-// For now, disable staged updates on Windows (see #18292).
+pref("app.update.notifyDuringDownload", true);
+pref("app.update.url.manual", "https://www.torproject.org/download/languages/");
+pref("app.update.url.details", "https://www.torproject.org/download/");
+pref("app.update.badgeWaitTime", 0);
+pref("app.releaseNotesURL", "about:blank");
+
+#ifndef XP_MACOSX
+// Disable staged updates on platforms other than macOS.
+// Staged updates do not work on Windows due to #18292.
+// Also, on Windows and Linux any changes that are made to the browser profile
+// or Tor data after an update is staged will be lost.
pref("app.update.staging.enabled", false);
#endif
@@ -82,6 +89,7 @@ pref("datareporting.policy.dataSubmissionEnabled", false);
// Make sure Unified Telemetry is really disabled, see: #18738.
pref("toolkit.telemetry.unified", false);
pref("toolkit.telemetry.enabled", false);
+pref("toolkit.telemetry.updatePing.enabled", false); // Make sure updater telemetry is disabled; see #25909.
#ifdef XP_WIN
// Defense-in-depth: ensure that the Windows default browser agent will
// not ping Mozilla if it is somehow present (we omit it at build time).
diff --git a/browser/app/profile/firefox.js b/browser/app/profile/firefox.js
index bd6a49adb350..ddca828996c1 100644
--- a/browser/app/profile/firefox.js
+++ b/browser/app/profile/firefox.js
@@ -134,14 +134,8 @@ pref("app.update.elevation.promptMaxAttempts", 2);
pref("app.update.notifyDuringDownload", false);
// If set to true, the Update Service will automatically download updates if the
-// user can apply updates. This pref is no longer used on Windows, except as the
-// default value to migrate to the new location that this data is now stored
-// (which is in a file in the update directory). Because of this, this pref
-// should no longer be used directly. Instead, getAppUpdateAutoEnabled and
-// getAppUpdateAutoEnabled from UpdateUtils.jsm should be used.
-#ifndef XP_WIN
- pref("app.update.auto", true);
-#endif
+// user can apply updates.
+pref("app.update.auto", true);
// If set to true, the Update Service will apply updates in the background
// when it finishes downloading them.
diff --git a/browser/base/content/aboutDialog-appUpdater.js b/browser/base/content/aboutDialog-appUpdater.js
index 6d7e9a5e5b7e..b5d5a5d38628 100644
--- a/browser/base/content/aboutDialog-appUpdater.js
+++ b/browser/base/content/aboutDialog-appUpdater.js
@@ -165,7 +165,7 @@ appUpdater.prototype = {
if (aChildID == "downloadAndInstall") {
let updateVersion = gAppUpdater.update.displayVersion;
// Include the build ID if this is an "a#" (nightly or aurora) build
- if (/a\d+$/.test(updateVersion)) {
+ if (!AppConstants.TOR_BROWSER_UPDATE && /a\d+$/.test(updateVersion)) {
let buildID = gAppUpdater.update.buildID;
let year = buildID.slice(0, 4);
let month = buildID.slice(4, 6);
diff --git a/browser/base/content/aboutDialog.js b/browser/base/content/aboutDialog.js
index b96337666cff..ab1d9b80b944 100644
--- a/browser/base/content/aboutDialog.js
+++ b/browser/base/content/aboutDialog.js
@@ -56,15 +56,13 @@ async function init(aEvent) {
bits: Services.appinfo.is64Bit ? 64 : 32,
};
+ // Adjust version text to show the Tor Browser version
+ versionAttributes.version = AppConstants.TOR_BROWSER_VERSION +
+ " (based on Mozilla Firefox " +
+ AppConstants.MOZ_APP_VERSION_DISPLAY + ")";
+
let version = Services.appinfo.version;
if (/a\d+$/.test(version)) {
- versionId = "aboutDialog-version-nightly";
- let buildID = Services.appinfo.appBuildID;
- let year = buildID.slice(0, 4);
- let month = buildID.slice(4, 6);
- let day = buildID.slice(6, 8);
- versionAttributes.isodate = `${year}-${month}-${day}`;
-
document.getElementById("experimental").hidden = false;
document.getElementById("communityDesc").hidden = true;
}
diff --git a/browser/components/BrowserContentHandler.jsm b/browser/components/BrowserContentHandler.jsm
index 97417d86cd7f..d8e24e641447 100644
--- a/browser/components/BrowserContentHandler.jsm
+++ b/browser/components/BrowserContentHandler.jsm
@@ -44,6 +44,8 @@ XPCOMUtils.defineLazyGetter(this, "gSystemPrincipal", () =>
);
XPCOMUtils.defineLazyGlobalGetters(this, [URL]);
+const kTBSavedVersionPref = "browser.startup.homepage_override.torbrowser.version";
+
// One-time startup homepage override configurations
const ONCE_DOMAINS = ["mozilla.org", "firefox.com"];
const ONCE_PREF = "browser.startup.homepage_override.once";
@@ -102,7 +104,8 @@ const OVERRIDE_NEW_BUILD_ID = 3;
* Returns:
* OVERRIDE_NEW_PROFILE if this is the first run with a new profile.
* OVERRIDE_NEW_MSTONE if this is the first run with a build with a different
- * Gecko milestone (i.e. right after an upgrade).
+ * Gecko milestone or Tor Browser version (i.e. right
+ * after an upgrade).
* OVERRIDE_NEW_BUILD_ID if this is the first run with a new build ID of the
* same Gecko milestone (i.e. after a nightly upgrade).
* OVERRIDE_NONE otherwise.
@@ -119,6 +122,11 @@ function needHomepageOverride(prefb) {
var mstone = Services.appinfo.platformVersion;
+ var savedTBVersion = null;
+ try {
+ savedTBVersion = prefb.getCharPref(kTBSavedVersionPref);
+ } catch (e) {}
+
var savedBuildID = prefb.getCharPref(
"browser.startup.homepage_override.buildID",
""
@@ -140,7 +148,22 @@ function needHomepageOverride(prefb) {
prefb.setCharPref("browser.startup.homepage_override.mstone", mstone);
prefb.setCharPref("browser.startup.homepage_override.buildID", buildID);
- return savedmstone ? OVERRIDE_NEW_MSTONE : OVERRIDE_NEW_PROFILE;
+ prefb.setCharPref(kTBSavedVersionPref, AppConstants.TOR_BROWSER_VERSION);
+
+ // After an upgrade from an older release of Tor Browser (<= 5.5a1), the
+ // savedmstone will be undefined because those releases included the
+ // value "ignore" for the browser.startup.homepage_override.mstone pref.
+ // To correctly detect an upgrade vs. a new profile, we check for the
+ // presence of the "app.update.postupdate" pref.
+ let updated = prefb.prefHasUserValue("app.update.postupdate");
+ return (savedmstone || updated) ? OVERRIDE_NEW_MSTONE
+ : OVERRIDE_NEW_PROFILE;
+ }
+
+ if (AppConstants.TOR_BROWSER_VERSION != savedTBVersion) {
+ prefb.setCharPref("browser.startup.homepage_override.buildID", buildID);
+ prefb.setCharPref(kTBSavedVersionPref, AppConstants.TOR_BROWSER_VERSION);
+ return OVERRIDE_NEW_MSTONE;
}
if (buildID != savedBuildID) {
@@ -624,6 +647,13 @@ nsBrowserContentHandler.prototype = {
"browser.startup.homepage_override.buildID",
"unknown"
);
+
+ // We do the same for the Tor Browser version.
+ let old_tbversion = null;
+ try {
+ old_tbversion = prefb.getCharPref(kTBSavedVersionPref);
+ } catch (e) {}
+
override = needHomepageOverride(prefb);
if (override != OVERRIDE_NONE) {
switch (override) {
@@ -650,9 +680,10 @@ nsBrowserContentHandler.prototype = {
"startup.homepage_override_url"
);
let update = UpdateManager.readyUpdate;
+ let old_version = old_tbversion ? old_tbversion: old_mstone;
if (
update &&
- Services.vc.compare(update.appVersion, old_mstone) > 0
+ Services.vc.compare(update.appVersion, old_version) > 0
) {
overridePage = getPostUpdateOverridePage(update, overridePage);
// Send the update ping to signal that the update was successful.
@@ -660,6 +691,8 @@ nsBrowserContentHandler.prototype = {
}
overridePage = overridePage.replace("%OLD_VERSION%", old_mstone);
+ overridePage = overridePage.replace("%OLD_TOR_BROWSER_VERSION%",
+ old_tbversion);
break;
case OVERRIDE_NEW_BUILD_ID:
if (UpdateManager.readyUpdate) {
diff --git a/browser/components/customizableui/content/panelUI.inc.xhtml b/browser/components/customizableui/content/panelUI.inc.xhtml
index 3def36d11e29..882cb4cce7f4 100644
--- a/browser/components/customizableui/content/panelUI.inc.xhtml
+++ b/browser/components/customizableui/content/panelUI.inc.xhtml
@@ -145,7 +145,8 @@
<popupnotification id="appMenu-update-restart-notification"
popupid="update-restart"
data-lazy-l10n-id="appmenu-update-restart2"
- data-l10n-attrs="buttonlabel, buttonaccesskey, secondarybuttonlabel, secondarybuttonaccesskey"
+ data-l10n-attrs="buttonaccesskey, secondarybuttonlabel, secondarybuttonaccesskey"
+ buttonlabel="&updateRestart.panelUI.label2;"
closebuttonhidden="true"
dropmarkerhidden="true"
checkboxhidden="true"
@@ -153,7 +154,7 @@
hasicon="true"
hidden="true">
<popupnotificationcontent id="update-restart-notification-content" orient="vertical">
- <description id="update-restart-description" data-lazy-l10n-id="appmenu-update-restart-message2"></description>
+ <description id="update-restart-description"> </description>
</popupnotificationcontent>
</popupnotification>
diff --git a/browser/confvars.sh b/browser/confvars.sh
index 92871c9516f9..040a27e9b92d 100755
--- a/browser/confvars.sh
+++ b/browser/confvars.sh
@@ -6,26 +6,6 @@
MOZ_APP_VENDOR=Mozilla
MOZ_UPDATER=1
-if test "$OS_ARCH" = "WINNT"; then
- if ! test "$HAVE_64BIT_BUILD"; then
- if test "$MOZ_UPDATE_CHANNEL" = "nightly" -o \
- "$MOZ_UPDATE_CHANNEL" = "nightly-try" -o \
- "$MOZ_UPDATE_CHANNEL" = "aurora" -o \
- "$MOZ_UPDATE_CHANNEL" = "beta" -o \
- "$MOZ_UPDATE_CHANNEL" = "release"; then
- if ! test "$MOZ_DEBUG"; then
- if ! test "$USE_STUB_INSTALLER"; then
- # Expect USE_STUB_INSTALLER from taskcluster for downstream task consistency
- echo "ERROR: STUB installer expected to be enabled but"
- echo "ERROR: USE_STUB_INSTALLER is not specified in the environment"
- exit 1
- fi
- MOZ_STUB_INSTALLER=1
- fi
- fi
- fi
-fi
-
BROWSER_CHROME_URL=chrome://browser/content/browser.xhtml
# MOZ_APP_DISPLAYNAME will be set by branding/configure.sh
@@ -38,6 +18,21 @@ MOZ_BRANDING_DIRECTORY=browser/branding/unofficial
MOZ_OFFICIAL_BRANDING_DIRECTORY=browser/branding/official
MOZ_APP_ID={ec8030f7-c20a-464f-9b0e-13a3a9e97384}
+# ACCEPTED_MAR_CHANNEL_IDS should usually be the same as the value MAR_CHANNEL_ID.
+# If more than one ID is needed, then you should use a comma separated list
+# of values.
+# The MAR_CHANNEL_ID must not contain the following 3 characters: ",\t "
+if test "$MOZ_UPDATE_CHANNEL" = "alpha"; then
+ ACCEPTED_MAR_CHANNEL_IDS=torbrowser-torproject-alpha
+ MAR_CHANNEL_ID=torbrowser-torproject-alpha
+elif test "$MOZ_UPDATE_CHANNEL" = "nightly"; then
+ ACCEPTED_MAR_CHANNEL_IDS=torbrowser-torproject-nightly
+ MAR_CHANNEL_ID=torbrowser-torproject-nightly
+else
+ ACCEPTED_MAR_CHANNEL_IDS=torbrowser-torproject-release
+ MAR_CHANNEL_ID=torbrowser-torproject-release
+fi
+
MOZ_PROFILE_MIGRATOR=1
# Include the DevTools client, not just the server (which is the default)
diff --git a/browser/installer/package-manifest.in b/browser/installer/package-manifest.in
index 13e4df002734..f0a60080cc39 100644
--- a/browser/installer/package-manifest.in
+++ b/browser/installer/package-manifest.in
@@ -36,8 +36,10 @@
; Mac bundle stuff
@APPNAME@/Contents/Info.plist
#ifdef MOZ_UPDATER
+#ifndef TOR_BROWSER_UPDATE
@APPNAME@/Contents/Library/LaunchServices
#endif
+#endif
@APPNAME@/Contents/PkgInfo
@RESPATH@/firefox.icns
@RESPATH@/document.icns
diff --git a/build/application.ini.in b/build/application.ini.in
index 6df13230a45b..9a0b162d447d 100644
--- a/build/application.ini.in
+++ b/build/application.ini.in
@@ -52,5 +52,5 @@ ServerURL=@MOZ_CRASHREPORTER_URL@/submit?id=@MOZ_APP_ID@&version=@MOZ_APP_VERSIO
#if MOZ_UPDATER
[AppUpdate]
-URL=https://@MOZ_APPUPDATE_HOST@/update/6/%PRODUCT%/%VERSION%/%BUILD_ID%/%BUILD_TARGET%/%LOCALE%/%CHANNEL%/%OS_VERSION%/%SYSTEM_CAPABILITIES%/%DISTRIBUTION%/%DISTRIBUTION_VERSION%/update.xml
+URL=https://aus1.torproject.org/torbrowser/update_3/%CHANNEL%/%BUILD_TARGET%/%VERSION%/%LOCALE%
#endif
diff --git a/build/moz.configure/init.configure b/build/moz.configure/init.configure
index 1bea5eead23a..aa0f383b66db 100644
--- a/build/moz.configure/init.configure
+++ b/build/moz.configure/init.configure
@@ -1181,7 +1181,6 @@ def version_path(path):
# set RELEASE_OR_BETA and NIGHTLY_BUILD variables depending on the cycle we're in
# The logic works like this:
# - if we have "a1" in GRE_MILESTONE, we're building Nightly (define NIGHTLY_BUILD)
-# - otherwise, if we have "a" in GRE_MILESTONE, we're building Nightly or Aurora
# - otherwise, we're building Release/Beta (define RELEASE_OR_BETA)
@depends(check_build_environment, build_project, version_path, "--help")
@imports(_from="__builtin__", _import="open")
@@ -1228,7 +1227,7 @@ def milestone(build_env, build_project, version_path, _):
if "a1" in milestone:
is_nightly = True
- elif "a" not in milestone:
+ else:
is_release_or_beta = True
major_version = milestone.split(".")[0]
diff --git a/config/createprecomplete.py b/config/createprecomplete.py
index dda4efcdf8e1..39aa85182dcb 100644
--- a/config/createprecomplete.py
+++ b/config/createprecomplete.py
@@ -5,6 +5,7 @@
# update instructions which is used to remove files and directories that are no
# longer present in a complete update. The current working directory is used for
# the location to enumerate and to create the precomplete file.
+# For symlinks, remove instructions are always generated.
from __future__ import absolute_import
from __future__ import unicode_literals
@@ -13,9 +14,18 @@ import os
import io
+# TODO When TOR_BROWSER_DATA_OUTSIDE_APP_DIR is used on all platforms,
+# we should remove all lines in this file that contain:
+# TorBrowser/Data
+
+
def get_build_entries(root_path):
"""Iterates through the root_path, creating a list for each file and
directory. Excludes any file paths ending with channel-prefs.js.
+ To support Tor Browser updates, excludes:
+ TorBrowser/Data/Browser/profiles.ini
+ TorBrowser/Data/Browser/profile.default/bookmarks.html
+ TorBrowser/Data/Tor/torrc
"""
rel_file_path_set = set()
rel_dir_path_set = set()
@@ -27,6 +37,10 @@ def get_build_entries(root_path):
if not (
rel_path_file.endswith("channel-prefs.js")
or rel_path_file.endswith("update-settings.ini")
+ or rel_path_file == "TorBrowser/Data/Browser/profiles.ini"
+ or rel_path_file
+ == "TorBrowser/Data/Browser/profile.default/bookmarks.html"
+ or rel_path_file == "TorBrowser/Data/Tor/torrc"
or rel_path_file.find("distribution/") != -1
):
rel_file_path_set.add(rel_path_file)
@@ -36,7 +50,10 @@ def get_build_entries(root_path):
rel_path_dir = os.path.join(parent_dir_rel_path, dir_name)
rel_path_dir = rel_path_dir.replace("\\", "/") + "/"
if rel_path_dir.find("distribution/") == -1:
- rel_dir_path_set.add(rel_path_dir)
+ if os.path.islink(rel_path_dir[:-1]):
+ rel_file_path_set.add(rel_path_dir[:-1])
+ else:
+ rel_dir_path_set.add(rel_path_dir)
rel_file_path_list = list(rel_file_path_set)
rel_file_path_list.sort(reverse=True)
diff --git a/devtools/client/aboutdebugging/src/actions/runtimes.js b/devtools/client/aboutdebugging/src/actions/runtimes.js
index 3d9ce0490bf2..00dff36f28a2 100644
--- a/devtools/client/aboutdebugging/src/actions/runtimes.js
+++ b/devtools/client/aboutdebugging/src/actions/runtimes.js
@@ -71,6 +71,11 @@ async function getRuntimeIcon(runtime, channel) {
}
}
+ // Use the release build skin for devtools within Tor Browser alpha releases.
+ if (channel === "alpha") {
+ return "chrome://devtools/skin/images/aboutdebugging-firefox-release.svg";
+ }
+
return channel === "release" || channel === "beta" || channel === "aurora"
? `chrome://devtools/skin/images/aboutdebugging-firefox-${channel}.svg`
: "chrome://devtools/skin/images/aboutdebugging-firefox-nightly.svg";
diff --git a/toolkit/modules/UpdateUtils.jsm b/toolkit/modules/UpdateUtils.jsm
index a1a2ac7898fb..fa840d6c0b2d 100644
--- a/toolkit/modules/UpdateUtils.jsm
+++ b/toolkit/modules/UpdateUtils.jsm
@@ -96,7 +96,7 @@ var UpdateUtils = {
case "PRODUCT":
return Services.appinfo.name;
case "VERSION":
- return Services.appinfo.version;
+ return AppConstants.TOR_BROWSER_VERSION;
case "BUILD_ID":
return Services.appinfo.appBuildID;
case "BUILD_TARGET":
@@ -160,7 +160,8 @@ var UpdateUtils = {
* downloads and installs updates. This corresponds to whether or not the user
* has selected "Automatically install updates" in about:preferences.
*
- * On Windows, this setting is shared across all profiles for the installation
+ * On Windows (except in Tor Browser), this setting is shared across all profiles
+ * for the installation
* and is read asynchronously from the file. On other operating systems, this
* setting is stored in a pref and is thus a per-profile setting.
*
@@ -176,7 +177,8 @@ var UpdateUtils = {
* updates" and "Check for updates but let you choose to install them" options
* in about:preferences.
*
- * On Windows, this setting is shared across all profiles for the installation
+ * On Windows (except in Tor Browser), this setting is shared across all profiles
+ * for the installation
* and is written asynchronously to the file. On other operating systems, this
* setting is stored in a pref and is thus a per-profile setting.
*
@@ -248,7 +250,7 @@ var UpdateUtils = {
// setting is just to propagate it from a pref observer. This ensures that
// the expected observers still get notified, even if a user manually
// changes the pref value.
- if (!UpdateUtils.PER_INSTALLATION_PREFS_SUPPORTED) {
+ if (AppConstants.TOR_BROWSER_UPDATE || !UpdateUtils.PER_INSTALLATION_PREFS_SUPPORTED) {
let initialConfig = {};
for (const [prefName, pref] of Object.entries(
UpdateUtils.PER_INSTALLATION_PREFS
@@ -317,7 +319,7 @@ var UpdateUtils = {
}
}
- if (!this.PER_INSTALLATION_PREFS_SUPPORTED) {
+ if (AppConstants.TOR_BROWSER_UPDATE || !this.PER_INSTALLATION_PREFS_SUPPORTED) {
// If we don't have per-installation prefs, we use regular preferences.
let prefValue = prefTypeFns.getProfilePref(prefName, pref.defaultValue);
return Promise.resolve(prefValue);
@@ -413,7 +415,7 @@ var UpdateUtils = {
);
}
- if (!this.PER_INSTALLATION_PREFS_SUPPORTED) {
+ if (AppConstants.TOR_BROWSER_UPDATE || !this.PER_INSTALLATION_PREFS_SUPPORTED) {
// If we don't have per-installation prefs, we use regular preferences.
if (options.setDefaultOnly) {
prefTypeFns.setProfileDefaultPref(prefName, value);
@@ -549,14 +551,6 @@ UpdateUtils.PER_INSTALLATION_PREFS = {
migrate: true,
observerTopic: "auto-update-config-change",
policyFn: () => {
- if (!Services.policies.isAllowed("app-auto-updates-off")) {
- // We aren't allowed to turn off auto-update - it is forced on.
- return true;
- }
- if (!Services.policies.isAllowed("app-auto-updates-on")) {
- // We aren't allowed to turn on auto-update - it is forced off.
- return false;
- }
return null;
},
},
diff --git a/toolkit/mozapps/extensions/AddonManager.jsm b/toolkit/mozapps/extensions/AddonManager.jsm
index 36d2220064cd..e2ccb5cc1d14 100644
--- a/toolkit/mozapps/extensions/AddonManager.jsm
+++ b/toolkit/mozapps/extensions/AddonManager.jsm
@@ -23,6 +23,7 @@ const { AppConstants } = ChromeUtils.import(
const MOZ_COMPATIBILITY_NIGHTLY = ![
"aurora",
+ "alpha",
"beta",
"release",
"esr",
@@ -37,6 +38,7 @@ const PREF_EM_AUTOUPDATE_DEFAULT = "extensions.update.autoUpdateDefault";
const PREF_EM_STRICT_COMPATIBILITY = "extensions.strictCompatibility";
const PREF_EM_CHECK_UPDATE_SECURITY = "extensions.checkUpdateSecurity";
const PREF_SYS_ADDON_UPDATE_ENABLED = "extensions.systemAddon.update.enabled";
+const PREF_EM_LAST_TORBROWSER_VERSION = "extensions.lastTorBrowserVersion";
const PREF_MIN_WEBEXT_PLATFORM_VERSION =
"extensions.webExtensionsMinPlatformVersion";
@@ -689,6 +691,28 @@ var AddonManagerInternal = {
);
}
+ // To ensure that extension and plugin code gets a chance to run
+ // after each browser update, set appChanged = true when the
+ // Tor Browser version has changed even if the Mozilla app
+ // version has not changed.
+ let tbChanged = undefined;
+ try {
+ tbChanged = AppConstants.TOR_BROWSER_VERSION !=
+ Services.prefs.getCharPref(PREF_EM_LAST_TORBROWSER_VERSION);
+ }
+ catch (e) { }
+ if (tbChanged !== false) {
+ // Because PREF_EM_LAST_TORBROWSER_VERSION was not present in older
+ // versions of Tor Browser, an app change is indicated when tbChanged
+ // is undefined or true.
+ if (appChanged === false) {
+ appChanged = true;
+ }
+
+ Services.prefs.setCharPref(PREF_EM_LAST_TORBROWSER_VERSION,
+ AppConstants.TOR_BROWSER_VERSION);
+ }
+
if (!MOZ_COMPATIBILITY_NIGHTLY) {
PREF_EM_CHECK_COMPATIBILITY =
PREF_EM_CHECK_COMPATIBILITY_BASE +
diff --git a/toolkit/mozapps/extensions/test/browser/head.js b/toolkit/mozapps/extensions/test/browser/head.js
index 4d81f2e1aac3..3a6876dd44bb 100644
--- a/toolkit/mozapps/extensions/test/browser/head.js
+++ b/toolkit/mozapps/extensions/test/browser/head.js
@@ -43,6 +43,7 @@ var PREF_CHECK_COMPATIBILITY;
var channel = Services.prefs.getCharPref("app.update.channel", "default");
if (
channel != "aurora" &&
+ channel != "alpha" &&
channel != "beta" &&
channel != "release" &&
channel != "esr"
diff --git a/toolkit/mozapps/extensions/test/xpcshell/head_addons.js b/toolkit/mozapps/extensions/test/xpcshell/head_addons.js
index cec0ffb401d6..3223ea970370 100644
--- a/toolkit/mozapps/extensions/test/xpcshell/head_addons.js
+++ b/toolkit/mozapps/extensions/test/xpcshell/head_addons.js
@@ -390,6 +390,7 @@ function isNightlyChannel() {
return (
channel != "aurora" &&
+ channel != "alpha" &&
channel != "beta" &&
channel != "release" &&
channel != "esr"
diff --git a/toolkit/mozapps/update/UpdateService.jsm b/toolkit/mozapps/update/UpdateService.jsm
index 10581c785074..f4f925992027 100644
--- a/toolkit/mozapps/update/UpdateService.jsm
+++ b/toolkit/mozapps/update/UpdateService.jsm
@@ -32,11 +32,15 @@ XPCOMUtils.defineLazyModuleGetters(this, {
AddonManager: "resource://gre/modules/AddonManager.jsm",
AsyncShutdown: "resource://gre/modules/AsyncShutdown.jsm",
CertUtils: "resource://gre/modules/CertUtils.jsm",
+#ifdef XP_WIN
ctypes: "resource://gre/modules/ctypes.jsm",
+#endif
DeferredTask: "resource://gre/modules/DeferredTask.jsm",
setTimeout: "resource://gre/modules/Timer.jsm",
UpdateUtils: "resource://gre/modules/UpdateUtils.jsm",
+#if !defined(TOR_BROWSER_UPDATE)
WindowsRegistry: "resource://gre/modules/WindowsRegistry.jsm",
+#endif
});
if (AppConstants.ENABLE_WEBDRIVER) {
@@ -513,6 +517,7 @@ function testWriteAccess(updateTestFile, createDirectory) {
updateTestFile.remove(false);
}
+#ifdef XP_WIN
/**
* Windows only function that closes a Win32 handle.
*
@@ -605,6 +610,7 @@ function getPerInstallationMutexName(aGlobal = true) {
(aGlobal ? "Global\\" : "") + "MozillaUpdateMutex-" + hasher.finish(true)
);
}
+#endif
/**
* Whether or not the current instance has the update mutex. The update mutex
@@ -615,6 +621,7 @@ function getPerInstallationMutexName(aGlobal = true) {
* @return true if this instance holds the update mutex
*/
function hasUpdateMutex() {
+#ifdef XP_WIN
if (AppConstants.platform != "win") {
return true;
}
@@ -622,6 +629,9 @@ function hasUpdateMutex() {
gUpdateMutexHandle = createMutex(getPerInstallationMutexName(true), false);
}
return !!gUpdateMutexHandle;
+#else
+ return true;
+#endif
}
/**
@@ -652,6 +662,11 @@ function areDirectoryEntriesWriteable(aDir) {
* @return true if elevation is required, false otherwise
*/
function getElevationRequired() {
+#if defined(TOR_BROWSER_UPDATE)
+ // To avoid potential security holes associated with running the updater
+ // process with elevated privileges, Tor Browser does not support elevation.
+ return false;
+#else
if (AppConstants.platform != "macosx") {
return false;
}
@@ -686,6 +701,7 @@ function getElevationRequired() {
"not required"
);
return false;
+#endif
}
/**
@@ -735,6 +751,7 @@ function getCanApplyUpdates() {
return false;
}
+#if !defined(TOR_BROWSER_UPDATE)
if (AppConstants.platform == "macosx") {
LOG(
"getCanApplyUpdates - bypass the write since elevation can be used " +
@@ -750,6 +767,7 @@ function getCanApplyUpdates() {
);
return true;
}
+#endif
try {
if (AppConstants.platform == "win") {
@@ -1589,6 +1607,9 @@ function handleUpdateFailure(update, errorCode) {
cancelations++;
Services.prefs.setIntPref(PREF_APP_UPDATE_CANCELATIONS, cancelations);
if (AppConstants.platform == "macosx") {
+#if defined(TOR_BROWSER_UPDATE)
+ cleanupActiveUpdate();
+#else
let osxCancelations = Services.prefs.getIntPref(
PREF_APP_UPDATE_CANCELATIONS_OSX,
0
@@ -1612,6 +1633,7 @@ function handleUpdateFailure(update, errorCode) {
(update.state = STATE_PENDING_ELEVATE)
);
}
+#endif
update.statusText = gUpdateBundle.GetStringFromName("elevationFailure");
} else {
writeStatusFile(getReadyUpdateDir(), (update.state = STATE_PENDING));
@@ -2206,7 +2228,26 @@ function Update(update) {
this._patches.push(patch);
}
- if (!this._patches.length && !update.hasAttribute("unsupported")) {
+ if (update.hasAttribute("unsupported")) {
+ this.unsupported = ("true" == update.getAttribute("unsupported"));
+ } else if (update.hasAttribute("minSupportedOSVersion")) {
+ let minOSVersion = update.getAttribute("minSupportedOSVersion");
+ try {
+ let osVersion = Services.sysinfo.getProperty("version");
+ this.unsupported = (Services.vc.compare(osVersion, minOSVersion) < 0);
+ } catch (e) {}
+ }
+ if (!this.unsupported && update.hasAttribute("minSupportedInstructionSet")) {
+ let minInstructionSet = update.getAttribute("minSupportedInstructionSet");
+ if (['MMX', 'SSE', 'SSE2', 'SSE3',
+ 'SSE4A', 'SSE4_1', 'SSE4_2'].indexOf(minInstructionSet) >= 0) {
+ try {
+ this.unsupported = !Services.sysinfo.getProperty("has" + minInstructionSet);
+ } catch (e) {}
+ }
+ }
+
+ if (!this._patches.length && !this.unsupported) {
throw Components.Exception("", Cr.NS_ERROR_ILLEGAL_VALUE);
}
@@ -2244,9 +2285,7 @@ function Update(update) {
if (!isNaN(attr.value)) {
this.promptWaitTime = parseInt(attr.value);
}
- } else if (attr.name == "unsupported") {
- this.unsupported = attr.value == "true";
- } else {
+ } else if (attr.name != "unsupported") {
switch (attr.name) {
case "appVersion":
case "buildID":
@@ -2271,7 +2310,11 @@ function Update(update) {
}
if (!this.previousAppVersion) {
+#ifdef TOR_BROWSER_UPDATE
+ this.previousAppVersion = AppConstants.TOR_BROWSER_VERSION;
+#else
this.previousAppVersion = Services.appinfo.version;
+#endif
}
if (!this.elevationFailure) {
@@ -2656,6 +2699,7 @@ UpdateService.prototype = {
Services.obs.removeObserver(this, topic);
Services.prefs.removeObserver(PREF_APP_UPDATE_LOG, this);
+#ifdef XP_WIN
if (AppConstants.platform == "win" && gUpdateMutexHandle) {
// If we hold the update mutex, let it go!
// The OS would clean this up sometime after shutdown,
@@ -2663,6 +2707,7 @@ UpdateService.prototype = {
closeHandle(gUpdateMutexHandle);
gUpdateMutexHandle = null;
}
+#endif
if (this._retryTimer) {
this._retryTimer.cancel();
}
@@ -2693,6 +2738,7 @@ UpdateService.prototype = {
}
break;
case "test-close-handle-update-mutex":
+#ifdef XP_WIN
if (Cu.isInAutomation) {
if (AppConstants.platform == "win" && gUpdateMutexHandle) {
LOG("UpdateService:observe - closing mutex handle for testing");
@@ -2700,6 +2746,7 @@ UpdateService.prototype = {
gUpdateMutexHandle = null;
}
}
+#endif
break;
}
},
@@ -2731,6 +2778,9 @@ UpdateService.prototype = {
return;
}
gUpdateFileWriteInfo = { phase: "startup", failure: false };
+#if defined(TOR_BROWSER_UPDATE) && !defined(XP_MACOSX)
+ this._removeOrphanedTorBrowserFiles();
+#endif
if (!this.canCheckForUpdates) {
LOG(
"UpdateService:_postUpdateProcessing - unable to check for " +
@@ -3042,6 +3092,42 @@ UpdateService.prototype = {
}
},
+#if defined(TOR_BROWSER_UPDATE) && !defined(XP_MACOSX)
+ /**
+ * When updating from an earlier version to Tor Browser 6.0 or later, old
+ * update info files are left behind on Linux and Windows. Remove them.
+ */
+ _removeOrphanedTorBrowserFiles: function AUS__removeOrphanedTorBrowserFiles() {
+ try {
+ let oldUpdateInfoDir = getAppBaseDir(); // aka the Browser directory.
+
+#ifdef XP_WIN
+ // On Windows, the updater files were stored under
+ // Browser/TorBrowser/Data/Browser/Caches/firefox/
+ oldUpdateInfoDir.appendRelativePath(
+ "TorBrowser\\Data\\Browser\\Caches\\firefox");
+#endif
+
+ // Remove the updates directory.
+ let updatesDir = oldUpdateInfoDir.clone();
+ updatesDir.append("updates");
+ if (updatesDir.exists() && updatesDir.isDirectory()) {
+ updatesDir.remove(true);
+ }
+
+ // Remove files: active-update.xml and updates.xml
+ let filesToRemove = [ "active-update.xml", "updates.xml" ];
+ filesToRemove.forEach(function(aFileName) {
+ let f = oldUpdateInfoDir.clone();
+ f.append(aFileName);
+ if (f.exists()) {
+ f.remove(false);
+ }
+ });
+ } catch (e) {}
+ },
+#endif
+
/**
* Register an observer when the network comes online, so we can short-circuit
* the app.update.interval when there isn't connectivity
@@ -3452,9 +3538,14 @@ UpdateService.prototype = {
updates.forEach(function(aUpdate) {
// Ignore updates for older versions of the application and updates for
// the same version of the application with the same build ID.
- if (
- vc.compare(aUpdate.appVersion, Services.appinfo.version) < 0 ||
- (vc.compare(aUpdate.appVersion, Services.appinfo.version) == 0 &&
+#ifdef TOR_BROWSER_UPDATE
+ let compatVersion = AppConstants.TOR_BROWSER_VERSION;
+#else
+ let compatVersion = Services.appinfo.version;
+#endif
+ let rc = vc.compare(aUpdate.appVersion, compatVersion);
+ if (rc < 0 ||
+ (rc == 0 &&
aUpdate.buildID == Services.appinfo.appBuildID)
) {
LOG(
@@ -3906,20 +3997,32 @@ UpdateService.prototype = {
// build ID. If we already have an update ready, we want to apply those
// same checks against the version of the ready update, so that we don't
// download an update that isn't newer than the one we already have.
+#ifdef TOR_BROWSER_UPDATE
+ let compatVersion = AppConstants.TOR_BROWSER_VERSION;
+#else
+ let compatVersion = Services.appinfo.version;
+#endif
if (
updateIsAtLeastAsOldAs(
update,
- Services.appinfo.version,
+ compatVersion,
Services.appinfo.appBuildID
)
) {
LOG(
"UpdateService:downloadUpdate - canceling download of update since " +
"it is for an earlier or same application version and build ID.\n" +
+#ifdef TOR_BROWSER_UPDATE
+ "current Tor Browser version: " +
+ compatVersion +
+ "\n" +
+ "update Tor Browser version : " +
+#else
"current application version: " +
- Services.appinfo.version +
+ compatVersion +
"\n" +
"update application version : " +
+#endif
update.appVersion +
"\n" +
"current build ID: " +
@@ -4599,6 +4702,7 @@ Checker.prototype = {
*/
_callback: null,
+#if !defined(TOR_BROWSER_UPDATE)
_getCanMigrate: function UC__getCanMigrate() {
if (AppConstants.platform != "win") {
return false;
@@ -4668,6 +4772,7 @@ Checker.prototype = {
LOG("Checker:_getCanMigrate - no registry entries for this installation");
return false;
},
+#endif // !defined(TOR_BROWSER_UPDATE)
/**
* The URL of the update service XML file to connect to that contains details
@@ -4696,9 +4801,11 @@ Checker.prototype = {
url += (url.includes("?") ? "&" : "?") + "force=1";
}
+#if !defined(TOR_BROWSER_UPDATE)
if (this._getCanMigrate()) {
url += (url.includes("?") ? "&" : "?") + "mig64=1";
}
+#endif
LOG("Checker:getUpdateURL - update URL: " + url);
return url;
diff --git a/toolkit/mozapps/update/UpdateServiceStub.jsm b/toolkit/mozapps/update/UpdateServiceStub.jsm
index 45b9177a06cb..ab4bbfc0884c 100644
--- a/toolkit/mozapps/update/UpdateServiceStub.jsm
+++ b/toolkit/mozapps/update/UpdateServiceStub.jsm
@@ -84,8 +84,12 @@ function UpdateServiceStub() {
// contains the status file's path
// We may need to migrate update data
+ // In Tor Browser we skip this because we do not use an update agent and we
+ // do not want to store any data outside of the browser installation directory.
+ // For more info, see https://bugzilla.mozilla.org/show_bug.cgi?id=1458314
if (
AppConstants.platform == "win" &&
+ !AppConstants.TOR_BROWSER_UPDATE &&
!Services.prefs.getBoolPref(prefUpdateDirMigrated, false)
) {
migrateUpdateDirectory();
diff --git a/toolkit/mozapps/update/common/updatehelper.cpp b/toolkit/mozapps/update/common/updatehelper.cpp
index b094d9eb75e9..c825d3c1ea8e 100644
--- a/toolkit/mozapps/update/common/updatehelper.cpp
+++ b/toolkit/mozapps/update/common/updatehelper.cpp
@@ -66,6 +66,13 @@ BOOL PathGetSiblingFilePath(LPWSTR destinationBuffer, LPCWSTR siblingFilePath,
* @return TRUE if successful
*/
BOOL GetSecureOutputDirectoryPath(LPWSTR outBuf) {
+#ifdef TOR_BROWSER_UPDATE
+ // This function is used to support the maintenance service and elevated
+ // updates and is therefore not called by Tor Browser's updater. We stub
+ // it out to avoid any chance that the Tor Browser updater will create
+ // files under C:\Program Files (x86)\ or a similar location.
+ return FALSE;
+#else
PWSTR progFilesX86;
if (FAILED(SHGetKnownFolderPath(FOLDERID_ProgramFilesX86, KF_FLAG_CREATE,
nullptr, &progFilesX86))) {
@@ -99,6 +106,7 @@ BOOL GetSecureOutputDirectoryPath(LPWSTR outBuf) {
}
return TRUE;
+#endif
}
/**
diff --git a/toolkit/mozapps/update/moz.build b/toolkit/mozapps/update/moz.build
index 0ed2f39f66a0..47af63a104b3 100644
--- a/toolkit/mozapps/update/moz.build
+++ b/toolkit/mozapps/update/moz.build
@@ -22,7 +22,6 @@ EXTRA_COMPONENTS += [
EXTRA_JS_MODULES += [
"UpdateListener.jsm",
- "UpdateService.jsm",
"UpdateServiceStub.jsm",
"UpdateTelemetry.jsm",
]
@@ -44,6 +43,10 @@ if (
"BackgroundTask_backgroundupdate.jsm",
]
+EXTRA_PP_JS_MODULES += [
+ "UpdateService.jsm",
+]
+
XPCOM_MANIFESTS += [
"components.conf",
]
diff --git a/toolkit/mozapps/update/updater/launchchild_osx.mm b/toolkit/mozapps/update/updater/launchchild_osx.mm
index 3074c0da065b..a48318ece4c3 100644
--- a/toolkit/mozapps/update/updater/launchchild_osx.mm
+++ b/toolkit/mozapps/update/updater/launchchild_osx.mm
@@ -372,6 +372,7 @@ bool ObtainUpdaterArguments(int* argc, char*** argv) {
@end
+#ifndef TOR_BROWSER_UPDATE
bool ServeElevatedUpdate(int argc, const char** argv) {
MacAutoreleasePool pool;
@@ -387,6 +388,7 @@ bool ServeElevatedUpdate(int argc, const char** argv) {
[updater release];
return didSucceed;
}
+#endif
bool IsOwnedByGroupAdmin(const char* aAppBundle) {
MacAutoreleasePool pool;
diff --git a/toolkit/mozapps/update/updater/moz.build b/toolkit/mozapps/update/updater/moz.build
index 40d7a77a6b62..ac7f82a4f9ad 100644
--- a/toolkit/mozapps/update/updater/moz.build
+++ b/toolkit/mozapps/update/updater/moz.build
@@ -51,7 +51,7 @@ xpcshell_cert.script = "gen_cert_header.py:create_header"
dep1_cert.script = "gen_cert_header.py:create_header"
dep2_cert.script = "gen_cert_header.py:create_header"
-if CONFIG["MOZ_UPDATE_CHANNEL"] in ("beta", "release", "esr"):
+if CONFIG["MOZ_UPDATE_CHANNEL"] in ("alpha", "beta", "release", "esr"):
primary_cert.inputs += ["release_primary.der"]
secondary_cert.inputs += ["release_secondary.der"]
elif CONFIG["MOZ_UPDATE_CHANNEL"] in (
diff --git a/toolkit/mozapps/update/updater/updater.cpp b/toolkit/mozapps/update/updater/updater.cpp
index 79cc918fbc69..d22233066157 100644
--- a/toolkit/mozapps/update/updater/updater.cpp
+++ b/toolkit/mozapps/update/updater/updater.cpp
@@ -16,7 +16,7 @@
* updatev3.manifest
* -----------------
* method = "add" | "add-if" | "add-if-not" | "patch" | "patch-if" |
- * "remove" | "rmdir" | "rmrfdir" | type
+ * "remove" | "rmdir" | "rmrfdir" | "addsymlink" | type
*
* 'add-if-not' adds a file if it doesn't exist.
*
@@ -78,7 +78,9 @@ bool IsRecursivelyWritable(const char* aPath);
void LaunchChild(int argc, const char** argv);
void LaunchMacPostProcess(const char* aAppBundle);
bool ObtainUpdaterArguments(int* argc, char*** argv);
+# ifndef TOR_BROWSER_UPDATE
bool ServeElevatedUpdate(int argc, const char** argv);
+# endif
void SetGroupOwnershipAndPermissions(const char* aAppBundle);
struct UpdateServerThreadArgs {
int argc;
@@ -489,9 +491,12 @@ static const NS_tchar* get_relative_path(const NS_tchar* fullpath) {
* The line from the manifest that contains the path.
* @param isdir
* Whether the path is a directory path. Defaults to false.
+ * @param islinktarget
+ * Whether the path is a symbolic link target. Defaults to false.
* @return valid filesystem path or nullptr if the path checks fail.
*/
-static NS_tchar* get_valid_path(NS_tchar** line, bool isdir = false) {
+static NS_tchar* get_valid_path(NS_tchar** line, bool isdir = false,
+ bool islinktarget = false) {
NS_tchar* path = mstrtok(kQuote, line);
if (!path) {
LOG(("get_valid_path: unable to determine path: " LOG_S, *line));
@@ -527,10 +532,12 @@ static NS_tchar* get_valid_path(NS_tchar** line, bool isdir = false) {
path[NS_tstrlen(path) - 1] = NS_T('\0');
}
- // Don't allow relative paths that resolve to a parent directory.
- if (NS_tstrstr(path, NS_T("..")) != nullptr) {
- LOG(("get_valid_path: paths must not contain '..': " LOG_S, path));
- return nullptr;
+ if (!islinktarget) {
+ // Don't allow relative paths that resolve to a parent directory.
+ if (NS_tstrstr(path, NS_T("..")) != nullptr) {
+ LOG(("get_valid_path: paths must not contain '..': " LOG_S, path));
+ return nullptr;
+ }
}
return path;
@@ -570,7 +577,7 @@ static void ensure_write_permissions(const NS_tchar* path) {
(void)_wchmod(path, _S_IREAD | _S_IWRITE);
#else
struct stat fs;
- if (!stat(path, &fs) && !(fs.st_mode & S_IWUSR)) {
+ if (!lstat(path, &fs) && !S_ISLNK(fs.st_mode) && !(fs.st_mode & S_IWUSR)) {
(void)chmod(path, fs.st_mode | S_IWUSR);
}
#endif
@@ -757,11 +764,9 @@ static int ensure_copy(const NS_tchar* path, const NS_tchar* dest) {
return READ_ERROR;
}
-# ifdef XP_UNIX
if (S_ISLNK(ss.st_mode)) {
return ensure_copy_symlink(path, dest);
}
-# endif
AutoFile infile(ensure_open(path, NS_T("rb"), ss.st_mode));
if (!infile) {
@@ -848,12 +853,19 @@ static int ensure_copy_recursive(const NS_tchar* path, const NS_tchar* dest,
return READ_ERROR;
}
-#ifdef XP_UNIX
+#ifndef XP_WIN
if (S_ISLNK(sInfo.st_mode)) {
return ensure_copy_symlink(path, dest);
}
#endif
+#ifdef XP_UNIX
+ // Ignore Unix domain sockets. See #20691.
+ if (S_ISSOCK(sInfo.st_mode)) {
+ return 0;
+ }
+#endif
+
if (!S_ISDIR(sInfo.st_mode)) {
return ensure_copy(path, dest);
}
@@ -910,7 +922,7 @@ static int rename_file(const NS_tchar* spath, const NS_tchar* dpath,
}
struct NS_tstat_t spathInfo;
- rv = NS_tstat(spath, &spathInfo);
+ rv = NS_tlstat(spath, &spathInfo); // Get info about file or symlink.
if (rv) {
LOG(("rename_file: failed to read file status info: " LOG_S ", "
"err: %d",
@@ -918,7 +930,12 @@ static int rename_file(const NS_tchar* spath, const NS_tchar* dpath,
return READ_ERROR;
}
- if (!S_ISREG(spathInfo.st_mode)) {
+#ifdef XP_WIN
+ if (!S_ISREG(spathInfo.st_mode))
+#else
+ if (!S_ISREG(spathInfo.st_mode) && !S_ISLNK(spathInfo.st_mode))
+#endif
+ {
if (allowDirs && !S_ISDIR(spathInfo.st_mode)) {
LOG(("rename_file: path present, but not a file: " LOG_S ", err: %d",
spath, errno));
@@ -927,7 +944,12 @@ static int rename_file(const NS_tchar* spath, const NS_tchar* dpath,
LOG(("rename_file: proceeding to rename the directory"));
}
- if (!NS_taccess(dpath, F_OK)) {
+#ifdef XP_WIN
+ if (!NS_taccess(dpath, F_OK))
+#else
+ if (!S_ISLNK(spathInfo.st_mode) && !NS_taccess(dpath, F_OK))
+#endif
+ {
if (ensure_remove(dpath)) {
LOG(
("rename_file: destination file exists and could not be "
@@ -947,7 +969,7 @@ static int rename_file(const NS_tchar* spath, const NS_tchar* dpath,
return OK;
}
-#ifdef XP_WIN
+#if defined(XP_WIN) && !defined(TOR_BROWSER_UPDATE)
// Remove the directory pointed to by path and all of its files and
// sub-directories. If a file is in use move it to the tobedeleted directory
// and attempt to schedule removal of the file on reboot
@@ -1046,7 +1068,19 @@ static int backup_restore(const NS_tchar* path, const NS_tchar* relPath) {
NS_tsnprintf(relBackup, sizeof(relBackup) / sizeof(relBackup[0]),
NS_T("%s") BACKUP_EXT, relPath);
- if (NS_taccess(backup, F_OK)) {
+ bool isLink = false;
+#ifndef XP_WIN
+ struct stat linkInfo;
+ int rv = lstat(backup, &linkInfo);
+ if (rv) {
+ LOG(("backup_restore: cannot get info for backup file: " LOG_S ", err: %d",
+ relBackup, errno));
+ return OK;
+ }
+ isLink = S_ISLNK(linkInfo.st_mode);
+#endif
+
+ if (!isLink && NS_taccess(backup, F_OK)) {
LOG(("backup_restore: backup file doesn't exist: " LOG_S, relBackup));
return OK;
}
@@ -1064,8 +1098,18 @@ static int backup_discard(const NS_tchar* path, const NS_tchar* relPath) {
NS_tsnprintf(relBackup, sizeof(relBackup) / sizeof(relBackup[0]),
NS_T("%s") BACKUP_EXT, relPath);
+ bool isLink = false;
+#ifndef XP_WIN
+ struct stat linkInfo;
+ int rv2 = lstat(backup, &linkInfo);
+ if (rv2) {
+ return OK; // File does not exist; nothing to do.
+ }
+ isLink = S_ISLNK(linkInfo.st_mode);
+#endif
+
// Nothing to discard
- if (NS_taccess(backup, F_OK)) {
+ if (!isLink && NS_taccess(backup, F_OK)) {
return OK;
}
@@ -1080,6 +1124,8 @@ static int backup_discard(const NS_tchar* path, const NS_tchar* relPath) {
relBackup, relPath));
return WRITE_ERROR_DELETE_BACKUP;
}
+
+# if !defined(TOR_BROWSER_UPDATE)
// The MoveFileEx call to remove the file on OS reboot will fail if the
// process doesn't have write access to the HKEY_LOCAL_MACHINE registry key
// but this is ok since the installer / uninstaller will delete the
@@ -1096,6 +1142,7 @@ static int backup_discard(const NS_tchar* path, const NS_tchar* relPath) {
"file: " LOG_S,
relPath));
}
+# endif
}
#else
if (rv) {
@@ -1150,7 +1197,7 @@ class Action {
class RemoveFile : public Action {
public:
- RemoveFile() : mSkip(0) {}
+ RemoveFile() : mSkip(0), mIsLink(0) {}
int Parse(NS_tchar* line) override;
int Prepare() override;
@@ -1161,6 +1208,7 @@ class RemoveFile : public Action {
mozilla::UniquePtr<NS_tchar[]> mFile;
mozilla::UniquePtr<NS_tchar[]> mRelPath;
int mSkip;
+ int mIsLink;
};
int RemoveFile::Parse(NS_tchar* line) {
@@ -1183,28 +1231,39 @@ int RemoveFile::Parse(NS_tchar* line) {
}
int RemoveFile::Prepare() {
- // Skip the file if it already doesn't exist.
- int rv = NS_taccess(mFile.get(), F_OK);
- if (rv) {
- mSkip = 1;
- mProgressCost = 0;
- return OK;
+ int rv;
+#ifndef XP_WIN
+ struct stat linkInfo;
+ rv = lstat(mFile.get(), &linkInfo);
+ mIsLink = ((0 == rv) && S_ISLNK(linkInfo.st_mode));
+#endif
+
+ if (!mIsLink) {
+ // Skip the file if it already doesn't exist.
+ rv = NS_taccess(mFile.get(), F_OK);
+ if (rv) {
+ mSkip = 1;
+ mProgressCost = 0;
+ return OK;
+ }
}
LOG(("PREPARE REMOVEFILE " LOG_S, mRelPath.get()));
- // Make sure that we're actually a file...
- struct NS_tstat_t fileInfo;
- rv = NS_tstat(mFile.get(), &fileInfo);
- if (rv) {
- LOG(("failed to read file status info: " LOG_S ", err: %d", mFile.get(),
- errno));
- return READ_ERROR;
- }
+ if (!mIsLink) {
+ // Make sure that we're actually a file...
+ struct NS_tstat_t fileInfo;
+ rv = NS_tstat(mFile.get(), &fileInfo);
+ if (rv) {
+ LOG(("failed to read file status info: " LOG_S ", err: %d", mFile.get(),
+ errno));
+ return READ_ERROR;
+ }
- if (!S_ISREG(fileInfo.st_mode)) {
- LOG(("path present, but not a file: " LOG_S, mFile.get()));
- return DELETE_ERROR_EXPECTED_FILE;
+ if (!S_ISREG(fileInfo.st_mode)) {
+ LOG(("path present, but not a file: " LOG_S, mFile.get()));
+ return DELETE_ERROR_EXPECTED_FILE;
+ }
}
NS_tchar* slash = (NS_tchar*)NS_tstrrchr(mFile.get(), NS_T('/'));
@@ -1233,7 +1292,13 @@ int RemoveFile::Execute() {
// The file is checked for existence here and in Prepare since it might have
// been removed by a separate instruction: bug 311099.
- int rv = NS_taccess(mFile.get(), F_OK);
+ int rv = 0;
+ if (mIsLink) {
+ struct NS_tstat_t linkInfo;
+ rv = NS_tlstat(mFile.get(), &linkInfo);
+ } else {
+ rv = NS_taccess(mFile.get(), F_OK);
+ }
if (rv) {
LOG(("file cannot be removed because it does not exist; skipping"));
mSkip = 1;
@@ -1956,6 +2021,92 @@ void PatchIfFile::Finish(int status) {
PatchFile::Finish(status);
}
+#ifndef XP_WIN
+class AddSymlink : public Action {
+ public:
+ AddSymlink() : mAdded(false) {}
+
+ virtual int Parse(NS_tchar* line);
+ virtual int Prepare();
+ virtual int Execute();
+ virtual void Finish(int status);
+
+ private:
+ mozilla::UniquePtr<NS_tchar[]> mLinkPath;
+ mozilla::UniquePtr<NS_tchar[]> mRelPath;
+ mozilla::UniquePtr<NS_tchar[]> mTarget;
+ bool mAdded;
+};
+
+int AddSymlink::Parse(NS_tchar* line) {
+ // format "<linkname>" "target"
+
+ NS_tchar* validPath = get_valid_path(&line);
+ if (!validPath) return PARSE_ERROR;
+
+ mRelPath = mozilla::MakeUnique<NS_tchar[]>(MAXPATHLEN);
+ NS_tstrcpy(mRelPath.get(), validPath);
+ mLinkPath.reset(get_full_path(validPath));
+ if (!mLinkPath) {
+ return PARSE_ERROR;
+ }
+
+ // consume whitespace between args
+ NS_tchar* q = mstrtok(kQuote, &line);
+ if (!q) return PARSE_ERROR;
+
+ validPath = get_valid_path(&line, false, true);
+ if (!validPath) return PARSE_ERROR;
+
+ mTarget = mozilla::MakeUnique<NS_tchar[]>(MAXPATHLEN);
+ NS_tstrcpy(mTarget.get(), validPath);
+
+ return OK;
+}
+
+int AddSymlink::Prepare() {
+ LOG(("PREPARE ADDSYMLINK " LOG_S " -> " LOG_S, mRelPath.get(),
+ mTarget.get()));
+
+ return OK;
+}
+
+int AddSymlink::Execute() {
+ LOG(("EXECUTE ADDSYMLINK " LOG_S " -> " LOG_S, mRelPath.get(),
+ mTarget.get()));
+
+ // First make sure that we can actually get rid of any existing file or link.
+ struct stat linkInfo;
+ int rv = lstat(mLinkPath.get(), &linkInfo);
+ if ((0 == rv) && !S_ISLNK(linkInfo.st_mode)) {
+ rv = NS_taccess(mLinkPath.get(), F_OK);
+ }
+ if (rv == 0) {
+ rv = backup_create(mLinkPath.get());
+ if (rv) return rv;
+ } else {
+ rv = ensure_parent_dir(mLinkPath.get());
+ if (rv) return rv;
+ }
+
+ // Create the link.
+ rv = symlink(mTarget.get(), mLinkPath.get());
+ if (!rv) {
+ mAdded = true;
+ }
+
+ return rv;
+}
+
+void AddSymlink::Finish(int status) {
+ LOG(("FINISH ADDSYMLINK " LOG_S " -> " LOG_S, mRelPath.get(), mTarget.get()));
+ // When there is an update failure and a link has been added it is removed
+ // here since there might not be a backup to replace it.
+ if (status && mAdded) NS_tremove(mLinkPath.get());
+ backup_finish(mLinkPath.get(), mRelPath.get(), status);
+}
+#endif
+
//-----------------------------------------------------------------------------
#ifdef XP_WIN
@@ -2278,14 +2429,29 @@ static bool IsSecureUpdateStatusSucceeded(bool& isSucceeded) {
*/
static int CopyInstallDirToDestDir() {
// These files should not be copied over to the updated app
-#ifdef XP_WIN
-# define SKIPLIST_COUNT 3
-#elif XP_MACOSX
-# define SKIPLIST_COUNT 0
+#if defined(TOR_BROWSER_UPDATE) && !defined(TOR_BROWSER_DATA_OUTSIDE_APP_DIR)
+# ifdef XP_WIN
+# define SKIPLIST_COUNT 6
+# else
+# define SKIPLIST_COUNT 5
+# endif
#else
-# define SKIPLIST_COUNT 2
+# ifdef XP_WIN
+# define SKIPLIST_COUNT 3
+# elif XP_MACOSX
+# define SKIPLIST_COUNT 0
+# else
+# define SKIPLIST_COUNT 2
+# endif
#endif
copy_recursive_skiplist<SKIPLIST_COUNT> skiplist;
+#if defined(TOR_BROWSER_UPDATE) && !defined(TOR_BROWSER_DATA_OUTSIDE_APP_DIR)
+# ifdef XP_MACOSX
+ skiplist.append(0, gInstallDirPath, NS_T("Updated.app"));
+ skiplist.append(1, gInstallDirPath, NS_T("TorBrowser/UpdateInfo/updates/0"));
+# endif
+#endif
+
#ifndef XP_MACOSX
skiplist.append(0, gInstallDirPath, NS_T("updated"));
skiplist.append(1, gInstallDirPath, NS_T("updates/0"));
@@ -2294,6 +2460,19 @@ static int CopyInstallDirToDestDir() {
# endif
#endif
+#if defined(TOR_BROWSER_UPDATE) && !defined(TOR_BROWSER_DATA_OUTSIDE_APP_DIR)
+# ifdef XP_WIN
+ skiplist.append(SKIPLIST_COUNT - 3, gInstallDirPath,
+ NS_T("TorBrowser/Data/Browser/profile.default/parent.lock"));
+# else
+ skiplist.append(SKIPLIST_COUNT - 3, gInstallDirPath,
+ NS_T("TorBrowser/Data/Browser/profile.default/.parentlock"));
+# endif
+
+ skiplist.append(SKIPLIST_COUNT - 1, gInstallDirPath,
+ NS_T("TorBrowser/Data/Tor/lock"));
+#endif
+
return ensure_copy_recursive(gInstallDirPath, gWorkingDirPath, skiplist);
}
@@ -2431,7 +2610,9 @@ static int ProcessReplaceRequest() {
if (NS_taccess(deleteDir, F_OK)) {
NS_tmkdir(deleteDir, 0755);
}
+# if !defined(TOR_BROWSER_UPDATE)
remove_recursive_on_reboot(tmpDir, deleteDir);
+# endif
#endif
}
@@ -2439,8 +2620,45 @@ static int ProcessReplaceRequest() {
// On OS X, we we need to remove the staging directory after its Contents
// directory has been moved.
NS_tchar updatedAppDir[MAXPATHLEN];
+# if defined(TOR_BROWSER_UPDATE) && !defined(TOR_BROWSER_DATA_OUTSIDE_APP_DIR)
+ NS_tsnprintf(updatedAppDir, sizeof(updatedAppDir) / sizeof(updatedAppDir[0]),
+ NS_T("%s/Updated.app"), gInstallDirPath);
+ // For Tor Browser on OS X, we also need to copy everything else that is
+ // inside Updated.app.
+ NS_tDIR* dir = NS_topendir(updatedAppDir);
+ if (dir) {
+ NS_tdirent* entry;
+ while ((entry = NS_treaddir(dir)) != 0) {
+ if (NS_tstrcmp(entry->d_name, NS_T(".")) &&
+ NS_tstrcmp(entry->d_name, NS_T(".."))) {
+ NS_tchar childSrcPath[MAXPATHLEN];
+ NS_tsnprintf(childSrcPath,
+ sizeof(childSrcPath) / sizeof(childSrcPath[0]),
+ NS_T("%s/%s"), updatedAppDir, entry->d_name);
+ NS_tchar childDstPath[MAXPATHLEN];
+ NS_tsnprintf(childDstPath,
+ sizeof(childDstPath) / sizeof(childDstPath[0]),
+ NS_T("%s/%s"), gInstallDirPath, entry->d_name);
+ ensure_remove_recursive(childDstPath);
+ rv = rename_file(childSrcPath, childDstPath, true);
+ if (rv) {
+ LOG(("Moving " LOG_S " to " LOG_S " failed, err: %d", childSrcPath,
+ childDstPath, errno));
+ }
+ }
+ }
+
+ NS_tclosedir(dir);
+ } else {
+ LOG(("Updated.app dir can't be found: " LOG_S ", err: %d", updatedAppDir,
+ errno));
+ }
+# else
NS_tsnprintf(updatedAppDir, sizeof(updatedAppDir) / sizeof(updatedAppDir[0]),
NS_T("%s/Updated.app"), gPatchDirPath);
+# endif
+
+ // Remove the Updated.app directory.
ensure_remove_recursive(updatedAppDir);
#endif
@@ -2614,11 +2832,15 @@ static void UpdateThreadFunc(void* param) {
#ifdef XP_MACOSX
static void ServeElevatedUpdateThreadFunc(void* param) {
+# ifdef TOR_BROWSER_UPDATE
+ WriteStatusFile(ELEVATION_CANCELED);
+# else
UpdateServerThreadArgs* threadArgs = (UpdateServerThreadArgs*)param;
gSucceeded = ServeElevatedUpdate(threadArgs->argc, threadArgs->argv);
if (!gSucceeded) {
WriteStatusFile(ELEVATION_CANCELED);
}
+# endif
QuitProgressUI();
}
@@ -2642,7 +2864,7 @@ int LaunchCallbackAndPostProcessApps(int argc, NS_tchar** argv,
#endif
) {
if (argc > callbackIndex) {
-#if defined(XP_WIN)
+#if defined(XP_WIN) && !defined(TOR_BROWSER_UPDATE)
if (gSucceeded) {
if (!LaunchWinPostProcess(gInstallDirPath, gPatchDirPath)) {
fprintf(stderr, "The post update process was not launched");
@@ -2726,8 +2948,12 @@ int NS_main(int argc, NS_tchar** argv) {
UmaskContext umaskContext(0);
bool isElevated =
+# ifdef TOR_BROWSER_UPDATE
+ false;
+# else
strstr(argv[0], "/Library/PrivilegedHelperTools/org.mozilla.updater") !=
0;
+# endif
if (isElevated) {
if (!ObtainUpdaterArguments(&argc, &argv)) {
// Won't actually get here because ObtainUpdaterArguments will terminate
@@ -3378,6 +3604,26 @@ int NS_main(int argc, NS_tchar** argv) {
// using the service is because we are testing.
if (!useService && !noServiceFallback &&
updateLockFileHandle == INVALID_HANDLE_VALUE) {
+# ifdef TOR_BROWSER_UPDATE
+# ifdef TOR_BROWSER_DATA_OUTSIDE_APP_DIR
+ // Because the TorBrowser-Data directory that contains the user's
+ // profile is a sibling of the Tor Browser installation directory,
+ // the user probably has permission to apply updates. Therefore, to
+ // avoid potential security issues such as CVE-2015-0833, do not
+ // attempt to elevate privileges. Instead, write a "failed" message
+ // to the update status file (this function will return immediately
+ // after the CloseHandle(elevatedFileHandle) call below).
+# else
+ // Because the user profile is contained within the Tor Browser
+ // installation directory, the user almost certainly has permission to
+ // apply updates. Therefore, to avoid potential security issues such
+ // as CVE-2015-0833, do not attempt to elevate privileges. Instead,
+ // write a "failed" message to the update status file (this function
+ // will return immediately after the CloseHandle(elevatedFileHandle)
+ // call below).
+# endif
+ WriteStatusFile(WRITE_ERROR_ACCESS_DENIED);
+# else
// Get the secure ID before trying to update so it is possible to
// determine if the updater has created a new one.
char uuidStringBefore[UUID_LEN] = {'\0'};
@@ -3423,6 +3669,7 @@ int NS_main(int argc, NS_tchar** argv) {
gCopyOutputFiles = false;
WriteStatusFile(ELEVATION_CANCELED);
}
+# endif
}
// If we started the elevated updater, and it finished, check the secure
@@ -3792,6 +4039,7 @@ int NS_main(int argc, NS_tchar** argv) {
if (!sStagedUpdate && !sReplaceRequest && _wrmdir(gDeleteDirPath)) {
LOG(("NS_main: unable to remove directory: " LOG_S ", err: %d", DELETE_DIR,
errno));
+# if !defined(TOR_BROWSER_UPDATE)
// The directory probably couldn't be removed due to it containing files
// that are in use and will be removed on OS reboot. The call to remove the
// directory on OS reboot is done after the calls to remove the files so the
@@ -3810,6 +4058,7 @@ int NS_main(int argc, NS_tchar** argv) {
"directory: " LOG_S,
DELETE_DIR));
}
+# endif
}
#endif /* XP_WIN */
@@ -4451,7 +4700,13 @@ int DoUpdate() {
action = new AddIfNotFile();
} else if (NS_tstrcmp(token, NS_T("patch-if")) == 0) { // Patch if exists
action = new PatchIfFile();
- } else {
+ }
+#ifndef XP_WIN
+ else if (NS_tstrcmp(token, NS_T("addsymlink")) == 0) {
+ action = new AddSymlink();
+ }
+#endif
+ else {
LOG(("DoUpdate: unknown token: " LOG_S, token));
free(buf);
return PARSE_ERROR;
diff --git a/toolkit/xre/MacLaunchHelper.h b/toolkit/xre/MacLaunchHelper.h
index f8dc75ee4d08..ce816acd83e2 100644
--- a/toolkit/xre/MacLaunchHelper.h
+++ b/toolkit/xre/MacLaunchHelper.h
@@ -17,7 +17,9 @@ extern "C" {
* pid of the terminated process to confirm that it executed successfully.
*/
void LaunchChildMac(int aArgc, char** aArgv, pid_t* aPid = 0);
+#ifndef TOR_BROWSER_UPDATE
bool LaunchElevatedUpdate(int aArgc, char** aArgv, pid_t* aPid = 0);
+#endif
}
#endif
diff --git a/toolkit/xre/MacLaunchHelper.mm b/toolkit/xre/MacLaunchHelper.mm
index ec570ffab124..da2917c2a99e 100644
--- a/toolkit/xre/MacLaunchHelper.mm
+++ b/toolkit/xre/MacLaunchHelper.mm
@@ -40,6 +40,7 @@ void LaunchChildMac(int aArgc, char** aArgv, pid_t* aPid) {
}
}
+#ifndef TOR_BROWSER_UPDATE
BOOL InstallPrivilegedHelper() {
AuthorizationRef authRef = NULL;
OSStatus status = AuthorizationCreate(
@@ -116,3 +117,4 @@ bool LaunchElevatedUpdate(int aArgc, char** aArgv, pid_t* aPid) {
}
return didSucceed;
}
+#endif
diff --git a/toolkit/xre/nsAppRunner.cpp b/toolkit/xre/nsAppRunner.cpp
index a14ab7c1965d..a1aeed07550f 100644
--- a/toolkit/xre/nsAppRunner.cpp
+++ b/toolkit/xre/nsAppRunner.cpp
@@ -3243,6 +3243,11 @@ static bool CheckCompatibility(nsIFile* aProfileDir, const nsCString& aVersion,
gLastAppBuildID.Assign(gAppData->buildID);
nsAutoCString buf;
+
+ nsAutoCString tbVersion(TOR_BROWSER_VERSION_QUOTED);
+ rv = parser.GetString("Compatibility", "LastTorBrowserVersion", buf);
+ if (NS_FAILED(rv) || !tbVersion.Equals(buf)) return false;
+
rv = parser.GetString("Compatibility", "LastOSABI", buf);
if (NS_FAILED(rv) || !aOSABI.Equals(buf)) return false;
@@ -3328,6 +3333,12 @@ static void WriteVersion(nsIFile* aProfileDir, const nsCString& aVersion,
PR_Write(fd, kHeader, sizeof(kHeader) - 1);
PR_Write(fd, aVersion.get(), aVersion.Length());
+ nsAutoCString tbVersion(TOR_BROWSER_VERSION_QUOTED);
+ static const char kTorBrowserVersionHeader[] =
+ NS_LINEBREAK "LastTorBrowserVersion=";
+ PR_Write(fd, kTorBrowserVersionHeader, sizeof(kTorBrowserVersionHeader) - 1);
+ PR_Write(fd, tbVersion.get(), tbVersion.Length());
+
static const char kOSABIHeader[] = NS_LINEBREAK "LastOSABI=";
PR_Write(fd, kOSABIHeader, sizeof(kOSABIHeader) - 1);
PR_Write(fd, aOSABI.get(), aOSABI.Length());
@@ -4724,8 +4735,17 @@ int XREMain::XRE_mainStartup(bool* aExitFlag) {
if (CheckArg("test-process-updates")) {
SaveToEnv("MOZ_TEST_PROCESS_UPDATES=1");
}
+# ifdef TOR_BROWSER_UPDATE
+ nsAutoCString compatVersion(TOR_BROWSER_VERSION_QUOTED);
+# endif
ProcessUpdates(mDirProvider.GetGREDir(), exeDir, updRoot, gRestartArgc,
- gRestartArgv, mAppData->version);
+ gRestartArgv,
+# ifdef TOR_BROWSER_UPDATE
+ compatVersion.get()
+# else
+ mAppData->version
+# endif
+ );
if (EnvHasValue("MOZ_TEST_PROCESS_UPDATES")) {
SaveToEnv("MOZ_TEST_PROCESS_UPDATES=");
*aExitFlag = true;
diff --git a/toolkit/xre/nsUpdateDriver.cpp b/toolkit/xre/nsUpdateDriver.cpp
index c85e7b98eb3f..f83f28288786 100644
--- a/toolkit/xre/nsUpdateDriver.cpp
+++ b/toolkit/xre/nsUpdateDriver.cpp
@@ -165,6 +165,13 @@ static nsresult GetInstallDirPath(nsIFile* appDir, nsACString& installDirPath) {
return NS_OK;
}
+#ifdef DEBUG
+static void dump_argv(const char* aPrefix, char** argv, int argc) {
+ printf("%s - %d args\n", aPrefix, argc);
+ for (int i = 0; i < argc; ++i) printf(" %d: %s\n", i, argv[i]);
+}
+#endif
+
static bool GetFile(nsIFile* dir, const nsACString& name,
nsCOMPtr<nsIFile>& result) {
nsresult rv;
@@ -226,6 +233,34 @@ typedef enum {
eAppliedService,
} UpdateStatus;
+#ifdef DEBUG
+static const char* UpdateStatusToString(UpdateStatus aStatus) {
+ const char* rv = "unknown";
+ switch (aStatus) {
+ case eNoUpdateAction:
+ rv = "NoUpdateAction";
+ break;
+ case ePendingUpdate:
+ rv = "PendingUpdate";
+ break;
+ case ePendingService:
+ rv = "PendingService";
+ break;
+ case ePendingElevate:
+ rv = "PendingElevate";
+ break;
+ case eAppliedUpdate:
+ rv = "AppliedUpdate";
+ break;
+ case eAppliedService:
+ rv = "AppliedService";
+ break;
+ }
+
+ return rv;
+}
+#endif
+
/**
* Returns a value indicating what needs to be done in order to handle an
* update.
@@ -298,9 +333,39 @@ static bool IsOlderVersion(nsIFile* versionFile, const char* appVersion) {
return false;
}
+#ifdef DEBUG
+ printf("IsOlderVersion checking appVersion %s against updateVersion %s\n",
+ appVersion, buf);
+#endif
+
return mozilla::Version(appVersion) > buf;
}
+#ifndef TOR_BROWSER_DATA_OUTSIDE_APP_DIR
+# if defined(TOR_BROWSER_UPDATE) && defined(XP_MACOSX)
+static nsresult GetUpdateDirFromAppDir(nsIFile* aAppDir, nsIFile** aResult) {
+ // On Mac OSX, we stage the update to an Updated.app directory that is
+ // directly below the main Tor Browser.app directory (two levels up from
+ // the appDir).
+ NS_ENSURE_ARG_POINTER(aAppDir);
+ NS_ENSURE_ARG_POINTER(aResult);
+ nsCOMPtr<nsIFile> parentDir1, parentDir2;
+ nsresult rv = aAppDir->GetParent(getter_AddRefs(parentDir1));
+ NS_ENSURE_SUCCESS(rv, rv);
+ rv = parentDir1->GetParent(getter_AddRefs(parentDir2));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ nsCOMPtr<nsIFile> updatedDir;
+ if (!GetFile(parentDir2, "Updated.app"_ns, updatedDir)) {
+ return NS_ERROR_FAILURE;
+ }
+
+ updatedDir.forget(aResult);
+ return NS_OK;
+}
+# endif
+#endif
+
/**
* Applies, switches, or stages an update.
*
@@ -448,7 +513,12 @@ static void ApplyUpdate(nsIFile* greDir, nsIFile* updateDir, nsIFile* appDir,
} else {
// Get the directory where the update is staged or will be staged.
#if defined(XP_MACOSX)
+# if defined(TOR_BROWSER_UPDATE) && !defined(TOR_BROWSER_DATA_OUTSIDE_APP_DIR)
+ rv = GetUpdateDirFromAppDir(appDir, getter_AddRefs(updatedDir));
+ if (NS_FAILED(rv)) {
+# else
if (!GetFile(updateDir, "Updated.app"_ns, updatedDir)) {
+# endif
#else
if (!GetFile(appDir, "updated"_ns, updatedDir)) {
#endif
@@ -543,6 +613,9 @@ static void ApplyUpdate(nsIFile* greDir, nsIFile* updateDir, nsIFile* appDir,
}
LOG(("spawning updater process [%s]\n", updaterPath.get()));
+#ifdef DEBUG
+ dump_argv("ApplyUpdate updater", argv, argc);
+#endif
#if defined(XP_UNIX) && !defined(XP_MACOSX)
// We use execv to spawn the updater process on all UNIX systems except Mac
@@ -581,6 +654,10 @@ static void ApplyUpdate(nsIFile* greDir, nsIFile* updateDir, nsIFile* appDir,
}
#elif defined(XP_MACOSX)
UpdateDriverSetupMacCommandLine(argc, argv, restart);
+# ifdef DEBUG
+dump_argv("ApplyUpdate after SetupMacCommandLine", argv, argc);
+# endif
+# ifndef TOR_BROWSER_UPDATE
// We need to detect whether elevation is required for this update. This can
// occur when an admin user installs the application, but another admin
// user attempts to update (see bug 394984).
@@ -593,6 +670,7 @@ if (restart && !IsRecursivelyWritable(installDirPath.get())) {
}
exit(0);
}
+# endif
if (isStaged) {
// Launch the updater to replace the installation with the staged updated.
@@ -663,9 +741,27 @@ static bool ProcessHasTerminated(ProcessType pt) {
nsresult ProcessUpdates(nsIFile* greDir, nsIFile* appDir, nsIFile* updRootDir,
int argc, char** argv, const char* appVersion,
bool restart, ProcessType* pid) {
+#if defined(XP_WIN) && defined(TOR_BROWSER_UPDATE)
+ // Try to remove the "tobedeleted" directory which, if present, contains
+ // files that could not be removed during a previous update (e.g., DLLs
+ // that were in use and therefore locked by Windows).
+ nsCOMPtr<nsIFile> deleteDir;
+ nsresult winrv = appDir->Clone(getter_AddRefs(deleteDir));
+ if (NS_SUCCEEDED(winrv)) {
+ winrv = deleteDir->AppendNative("tobedeleted"_ns);
+ if (NS_SUCCEEDED(winrv)) {
+ winrv = deleteDir->Remove(true);
+ }
+ }
+#endif
+
nsresult rv;
nsCOMPtr<nsIFile> updatesDir;
+#ifdef DEBUG
+ printf("ProcessUpdates updateRootDir: %s appVersion: %s\n",
+ updRootDir->HumanReadablePath().get(), appVersion);
+#endif
rv = updRootDir->Clone(getter_AddRefs(updatesDir));
NS_ENSURE_SUCCESS(rv, rv);
rv = updatesDir->AppendNative("updates"_ns);
@@ -685,6 +781,12 @@ nsresult ProcessUpdates(nsIFile* greDir, nsIFile* appDir, nsIFile* updRootDir,
nsCOMPtr<nsIFile> statusFile;
UpdateStatus status = GetUpdateStatus(updatesDir, statusFile);
+#ifdef DEBUG
+ printf("ProcessUpdates status: %s (%d)\n", UpdateStatusToString(status),
+ status);
+ printf("ProcessUpdates updatesDir: %s\n",
+ updatesDir->HumanReadablePath().get());
+#endif
switch (status) {
case ePendingUpdate:
case ePendingService: {
@@ -748,13 +850,16 @@ nsUpdateProcessor::ProcessUpdate() {
NS_ENSURE_SUCCESS(rv, rv);
}
+ nsAutoCString appVersion;
+#ifdef TOR_BROWSER_UPDATE
+ appVersion = TOR_BROWSER_VERSION_QUOTED;
+#else
nsCOMPtr<nsIXULAppInfo> appInfo =
do_GetService("@mozilla.org/xre/app-info;1", &rv);
NS_ENSURE_SUCCESS(rv, rv);
-
- nsAutoCString appVersion;
rv = appInfo->GetVersion(appVersion);
NS_ENSURE_SUCCESS(rv, rv);
+#endif
// Copy the parameters to the StagedUpdateInfo structure shared with the
// watcher thread.
diff --git a/toolkit/xre/nsXREDirProvider.cpp b/toolkit/xre/nsXREDirProvider.cpp
index a29e909a0bd9..122c0bac1bd3 100644
--- a/toolkit/xre/nsXREDirProvider.cpp
+++ b/toolkit/xre/nsXREDirProvider.cpp
@@ -1246,6 +1246,41 @@ nsresult nsXREDirProvider::GetUpdateRootDir(nsIFile** aResult,
}
#endif
nsCOMPtr<nsIFile> updRoot;
+#if defined(TOR_BROWSER_UPDATE)
+ // For Tor Browser, we store update history, etc. within the UpdateInfo
+ // directory under the user data directory.
+ nsresult rv = GetTorBrowserUserDataDir(getter_AddRefs(updRoot));
+ NS_ENSURE_SUCCESS(rv, rv);
+ rv = updRoot->AppendNative("UpdateInfo"_ns);
+ NS_ENSURE_SUCCESS(rv, rv);
+# if defined(XP_MACOSX) && defined(TOR_BROWSER_DATA_OUTSIDE_APP_DIR)
+ // Since the TorBrowser-Data directory may be shared among different
+ // installations of the application, embed the app path in the update dir
+ // so that the update history is partitioned. This is much less likely to
+ // be an issue on Linux or Windows because the Tor Browser packages for
+ // those platforms include a "container" folder that provides partitioning
+ // by default, and we do not support use of a shared, OS-recommended area
+ // for user data on those platforms.
+ nsCOMPtr<nsIFile> appFile;
+ bool per = false;
+ rv = GetFile(XRE_EXECUTABLE_FILE, &per, getter_AddRefs(appFile));
+ NS_ENSURE_SUCCESS(rv, rv);
+ nsCOMPtr<nsIFile> appRootDirFile;
+ nsAutoString appDirPath;
+ if (NS_FAILED(appFile->GetParent(getter_AddRefs(appRootDirFile))) ||
+ NS_FAILED(appRootDirFile->GetPath(appDirPath))) {
+ return NS_ERROR_FAILURE;
+ }
+
+ int32_t dotIndex = appDirPath.RFind(".app");
+ if (dotIndex == kNotFound) {
+ dotIndex = appDirPath.Length();
+ }
+ appDirPath = Substring(appDirPath, 1, dotIndex - 1);
+ rv = updRoot->AppendRelativePath(appDirPath);
+ NS_ENSURE_SUCCESS(rv, rv);
+# endif
+#else // ! TOR_BROWSER_UPDATE
nsCOMPtr<nsIFile> appFile;
bool per = false;
nsresult rv = GetFile(XRE_EXECUTABLE_FILE, &per, getter_AddRefs(appFile));
@@ -1253,7 +1288,7 @@ nsresult nsXREDirProvider::GetUpdateRootDir(nsIFile** aResult,
rv = appFile->GetParent(getter_AddRefs(updRoot));
NS_ENSURE_SUCCESS(rv, rv);
-#ifdef XP_MACOSX
+# ifdef XP_MACOSX
nsCOMPtr<nsIFile> appRootDirFile;
nsCOMPtr<nsIFile> localDir;
nsAutoString appDirPath;
@@ -1287,7 +1322,7 @@ nsresult nsXREDirProvider::GetUpdateRootDir(nsIFile** aResult,
localDir.forget(aResult);
return NS_OK;
-#elif XP_WIN
+# elif XP_WIN
nsAutoString installPath;
rv = updRoot->GetPath(installPath);
NS_ENSURE_SUCCESS(rv, rv);
@@ -1316,7 +1351,8 @@ nsresult nsXREDirProvider::GetUpdateRootDir(nsIFile** aResult,
nsAutoString updatePathStr;
updatePathStr.Assign(updatePath.get());
updRoot->InitWithPath(updatePathStr);
-#endif // XP_WIN
+# endif // XP_WIN
+#endif // ! TOR_BROWSER_UPDATE
updRoot.forget(aResult);
return NS_OK;
}
diff --git a/tools/update-packaging/common.sh b/tools/update-packaging/common.sh
index 4b994f30169c..26eabbf31379 100755
--- a/tools/update-packaging/common.sh
+++ b/tools/update-packaging/common.sh
@@ -8,6 +8,10 @@
# Author: Darin Fisher
#
+# TODO When TOR_BROWSER_DATA_OUTSIDE_APP_DIR is used on all platforms,
+# we should remove all lines in this file that contain:
+# TorBrowser/Data
+
# -----------------------------------------------------------------------------
QUIET=0
@@ -76,17 +80,8 @@ make_add_instruction() {
forced=
fi
- is_extension=$(echo "$f" | grep -c 'distribution/extensions/.*/')
- if [ $is_extension = "1" ]; then
- # Use the subdirectory of the extensions folder as the file to test
- # before performing this add instruction.
- testdir=$(echo "$f" | sed 's/\(.*distribution\/extensions\/[^\/]*\)\/.*/\1/')
- verbose_notice " add-if \"$testdir\" \"$f\""
- echo "add-if \"$testdir\" \"$f\"" >> "$filev3"
- else
- verbose_notice " add \"$f\"$forced"
- echo "add \"$f\"" >> "$filev3"
- fi
+ verbose_notice " add \"$f\"$forced"
+ echo "add \"$f\"" >> "$filev3"
}
check_for_add_if_not_update() {
@@ -109,21 +104,21 @@ make_add_if_not_instruction() {
echo "add-if-not \"$f\" \"$f\"" >> "$filev3"
}
+make_addsymlink_instruction() {
+ link="$1"
+ target="$2"
+ filev3="$3"
+
+ verbose_notice " addsymlink: $link -> $target"
+ echo "addsymlink \"$link\" \"$target\"" >> "$filev3"
+}
+
make_patch_instruction() {
f="$1"
filev3="$2"
- is_extension=$(echo "$f" | grep -c 'distribution/extensions/.*/')
- if [ $is_extension = "1" ]; then
- # Use the subdirectory of the extensions folder as the file to test
- # before performing this add instruction.
- testdir=$(echo "$f" | sed 's/\(.*distribution\/extensions\/[^\/]*\)\/.*/\1/')
- verbose_notice " patch-if \"$testdir\" \"$f.patch\" \"$f\""
- echo "patch-if \"$testdir\" \"$f.patch\" \"$f\"" >> "$filev3"
- else
- verbose_notice " patch \"$f.patch\" \"$f\""
- echo "patch \"$f.patch\" \"$f\"" >> "$filev3"
- fi
+ verbose_notice " patch \"$f.patch\" \"$f\""
+ echo "patch \"$f.patch\" \"$f\"" >> "$filev3"
}
append_remove_instructions() {
@@ -168,6 +163,10 @@ append_remove_instructions() {
# List all files in the current directory, stripping leading "./"
# Pass a variable name and it will be filled as an array.
+# To support Tor Browser updates, skip the following files:
+# TorBrowser/Data/Browser/profiles.ini
+# TorBrowser/Data/Browser/profile.default/bookmarks.html
+# TorBrowser/Data/Tor/torrc
list_files() {
count=0
temp_filelist=$(mktemp)
@@ -178,6 +177,11 @@ list_files() {
| sed 's/\.\/\(.*\)/\1/' \
| sort -r > "${temp_filelist}"
while read file; do
+ if [ "$file" = "TorBrowser/Data/Browser/profiles.ini" -o \
+ "$file" = "TorBrowser/Data/Browser/profile.default/bookmarks.html" -o \
+ "$file" = "TorBrowser/Data/Tor/torrc" ]; then
+ continue;
+ fi
eval "${1}[$count]=\"$file\""
(( count++ ))
done < "${temp_filelist}"
@@ -199,3 +203,19 @@ list_dirs() {
done < "${temp_dirlist}"
rm "${temp_dirlist}"
}
+
+# List all symbolic links in the current directory, stripping leading "./"
+list_symlinks() {
+ count=0
+
+ find . -type l \
+ | sed 's/\.\/\(.*\)/\1/' \
+ | sort -r > "temp-symlinklist"
+ while read symlink; do
+ target=$(readlink "$symlink")
+ eval "${1}[$count]=\"$symlink\""
+ eval "${2}[$count]=\"$target\""
+ (( count++ ))
+ done < "temp-symlinklist"
+ rm "temp-symlinklist"
+}
diff --git a/tools/update-packaging/make_full_update.sh b/tools/update-packaging/make_full_update.sh
index db2c5898efdc..603988997405 100755
--- a/tools/update-packaging/make_full_update.sh
+++ b/tools/update-packaging/make_full_update.sh
@@ -71,6 +71,7 @@ if [ ! -f "precomplete" ]; then
fi
list_files files
+list_symlinks symlinks symlink_targets
popd
@@ -81,6 +82,21 @@ notice "Adding type instruction to update manifests"
notice " type complete"
echo "type \"complete\"" >> "$updatemanifestv3"
+# TODO When TOR_BROWSER_DATA_OUTSIDE_APP_DIR is used on all platforms,
+# we should remove the following lines:
+# If removal of any old, existing directories is desired, emit the appropriate
+# rmrfdir commands.
+notice ""
+notice "Adding directory removal instructions to update manifests"
+for dir_to_remove in $directories_to_remove; do
+ # rmrfdir requires a trailing slash; if slash is missing, add one.
+ if ! [[ "$dir_to_remove" =~ /$ ]]; then
+ dir_to_remove="${dir_to_remove}/"
+ fi
+ echo "rmrfdir \"$dir_to_remove\"" >> "$updatemanifestv3"
+done
+# END TOR_BROWSER_DATA_OUTSIDE_APP_DIR removal
+
notice ""
notice "Adding file add instructions to update manifests"
num_files=${#files[*]}
@@ -102,6 +118,15 @@ for ((i=0; $i<$num_files; i=$i+1)); do
targetfiles="$targetfiles \"$f\""
done
+notice ""
+notice "Adding symlink add instructions to update manifests"
+num_symlinks=${#symlinks[*]}
+for ((i=0; $i<$num_symlinks; i=$i+1)); do
+ link="${symlinks[$i]}"
+ target="${symlink_targets[$i]}"
+ make_addsymlink_instruction "$link" "$target" "$updatemanifestv3"
+done
+
# Append remove instructions for any dead files.
notice ""
notice "Adding file and directory remove instructions from file 'removed-files'"
diff --git a/tools/update-packaging/make_incremental_update.sh b/tools/update-packaging/make_incremental_update.sh
index 24d68616731a..1adfef8fd96e 100755
--- a/tools/update-packaging/make_incremental_update.sh
+++ b/tools/update-packaging/make_incremental_update.sh
@@ -78,7 +78,11 @@ if [ $# = 0 ]; then
exit 1
fi
-requested_forced_updates='Contents/MacOS/firefox'
+# Firefox uses requested_forced_updates='Contents/MacOS/firefox' due to
+# 770996 but in Tor Browser we do not need that fix.
+requested_forced_updates=""
+directories_to_remove=""
+extra_files_to_remove=""
while getopts "hqf:" flag
do
@@ -114,6 +118,28 @@ workdir="$(mktemp -d)"
updatemanifestv3="$workdir/updatev3.manifest"
archivefiles="updatev3.manifest"
+# TODO When TOR_BROWSER_DATA_OUTSIDE_APP_DIR is used on all platforms,
+# we should remove the following lines:
+# If the NoScript extension has changed between
+# releases, add it to the "force updates" list.
+ext_path='TorBrowser/Data/Browser/profile.default/extensions'
+if [ -d "$newdir/$ext_path" ]; then
+ noscript='{73a6fe31-595d-460b-a920-fcc0f8843232}.xpi'
+
+ # NoScript is a packed extension, so we simply compare the old and the new
+ # .xpi files.
+ noscript_path="$ext_path/$noscript"
+ diff -a "$olddir/$noscript_path" "$newdir/$noscript_path" > /dev/null
+ rc=$?
+ if [ $rc -gt 1 ]; then
+ notice "Unexpected exit $rc from $noscript_path diff command"
+ exit 2
+ elif [ $rc -eq 1 ]; then
+ requested_forced_updates="$requested_forced_updates $noscript_path"
+ fi
+fi
+# END TOR_BROWSER_DATA_OUTSIDE_APP_DIR removal
+
mkdir -p "$workdir"
# Generate a list of all files in the target directory.
@@ -124,6 +150,7 @@ fi
list_files oldfiles
list_dirs olddirs
+list_symlinks oldsymlinks oldsymlink_targets
popd
@@ -141,6 +168,7 @@ fi
list_dirs newdirs
list_files newfiles
+list_symlinks newsymlinks newsymlink_targets
popd
@@ -151,6 +179,22 @@ notice "Adding type instruction to update manifests"
notice " type partial"
echo "type \"partial\"" >> $updatemanifestv3
+# TODO When TOR_BROWSER_DATA_OUTSIDE_APP_DIR is used on all platforms,
+# we should remove the following lines:
+# If removal of any old, existing directories is desired, emit the appropriate
+# rmrfdir commands.
+notice ""
+notice "Adding directory removal instructions to update manifests"
+for dir_to_remove in $directories_to_remove; do
+ # rmrfdir requires a trailing slash, so add one if missing.
+ if ! [[ "$dir_to_remove" =~ /$ ]]; then
+ dir_to_remove="${dir_to_remove}/"
+ fi
+ echo "rmrfdir \"$dir_to_remove\"" >> "$updatemanifestv3"
+done
+# END TOR_BROWSER_DATA_OUTSIDE_APP_DIR removal
+
+
notice ""
notice "Adding file patch and add instructions to update manifests"
@@ -242,6 +286,23 @@ for ((i=0; $i<$num_oldfiles; i=$i+1)); do
fi
done
+# Remove and re-add symlinks
+notice ""
+notice "Adding symlink remove/add instructions to update manifests"
+num_oldsymlinks=${#oldsymlinks[*]}
+for ((i=0; $i<$num_oldsymlinks; i=$i+1)); do
+ link="${oldsymlinks[$i]}"
+ verbose_notice " remove: $link"
+ echo "remove \"$link\"" >> "$updatemanifestv3"
+done
+
+num_newsymlinks=${#newsymlinks[*]}
+for ((i=0; $i<$num_newsymlinks; i=$i+1)); do
+ link="${newsymlinks[$i]}"
+ target="${newsymlink_targets[$i]}"
+ make_addsymlink_instruction "$link" "$target" "$updatemanifestv3"
+done
+
# Newly added files
notice ""
notice "Adding file add instructions to update manifests"
@@ -286,6 +347,14 @@ notice ""
notice "Adding file and directory remove instructions from file 'removed-files'"
append_remove_instructions "$newdir" "$updatemanifestv3"
+# TODO When TOR_BROWSER_DATA_OUTSIDE_APP_DIR is used on all platforms,
+# we should remove the following lines:
+for f in $extra_files_to_remove; do
+ notice " remove \"$f\""
+ echo "remove \"$f\"" >> "$updatemanifestv3"
+done
+# END TOR_BROWSER_DATA_OUTSIDE_APP_DIR removal
+
notice ""
notice "Adding directory remove instructions for directories that no longer exist"
num_olddirs=${#olddirs[*]}
1
0
[tor-browser/tor-browser-90.0b12-10.5-1] Bug 21830: Copying large text from web console leaks to /tmp
by sysrqb@torproject.org 02 Jul '21
by sysrqb@torproject.org 02 Jul '21
02 Jul '21
commit 0e45a41f4adc9f22df84adb1a24f19d2661709f2
Author: Georg Koppen <gk(a)torproject.org>
Date: Fri Aug 4 05:55:49 2017 +0000
Bug 21830: Copying large text from web console leaks to /tmp
Patch written by Neill Miller
---
widget/nsTransferable.cpp | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/widget/nsTransferable.cpp b/widget/nsTransferable.cpp
index c82549a4d1d1..f8ecfbff0983 100644
--- a/widget/nsTransferable.cpp
+++ b/widget/nsTransferable.cpp
@@ -33,6 +33,7 @@ Notes to self:
#include "nsILoadContext.h"
#include "nsXULAppAPI.h"
#include "mozilla/UniquePtr.h"
+#include "mozilla/Preferences.h"
using namespace mozilla;
@@ -195,6 +196,11 @@ nsTransferable::Init(nsILoadContext* aContext) {
if (aContext) {
mPrivateData = aContext->UsePrivateBrowsing();
+ } else {
+ // without aContext here to provide PrivateBrowsing information,
+ // we defer to the active configured setting
+ mPrivateData =
+ mozilla::Preferences::GetBool("browser.privatebrowsing.autostart");
}
#ifdef DEBUG
mInitialized = true;
1
0
[tor-browser/tor-browser-90.0b12-10.5-1] Bug 25658: Replace security slider with security level UI
by sysrqb@torproject.org 02 Jul '21
by sysrqb@torproject.org 02 Jul '21
02 Jul '21
commit d19996209248e877850c18236b4c1f717a9bff94
Author: Richard Pospesel <richard(a)torproject.org>
Date: Mon Mar 4 16:09:51 2019 -0800
Bug 25658: Replace security slider with security level UI
This patch adds a new 'securitylevel' component to Tor Browser intended
to replace the torbutton 'Security Slider'.
This component adds a new Security Level toolbar button which visually
indicates the current global security level via icon (as defined by the
extensions.torbutton.security_slider pref), a drop-down hanger with a
short description of the current security level, and a new section in
the about:preferences#privacy page where users can change their current
security level. In addition, the hanger and the preferences page will
show a visual warning when the user has modified prefs associated with
the security level and provide a one-click 'Restore Defaults' button to
get the user back on recommended settings.
Strings used by this patch are pulled from the torbutton extension, but
en-US defaults are provided if there is an error loading from the
extension. With this patch applied, the usual work-flow of "./mach build
&& ./mach run" work as expected, even if the torbutton extension is
disabled.
---
browser/base/content/browser.js | 10 +
browser/base/content/browser.xhtml | 5 +
browser/components/moz.build | 1 +
browser/components/preferences/preferences.xhtml | 1 +
browser/components/preferences/privacy.inc.xhtml | 2 +
browser/components/preferences/privacy.js | 19 +
.../securitylevel/content/securityLevel.js | 501 +++++++++++++++++++++
.../securitylevel/content/securityLevelButton.css | 9 +
.../content/securityLevelButton.inc.xhtml | 7 +
.../securitylevel/content/securityLevelButton.svg | 21 +
.../securitylevel/content/securityLevelPanel.css | 82 ++++
.../content/securityLevelPanel.inc.xhtml | 38 ++
.../content/securityLevelPreferences.css | 26 ++
.../content/securityLevelPreferences.inc.xhtml | 62 +++
browser/components/securitylevel/jar.mn | 6 +
browser/components/securitylevel/moz.build | 1 +
16 files changed, 791 insertions(+)
diff --git a/browser/base/content/browser.js b/browser/base/content/browser.js
index ebecec03eb5d..32a35dd3dddc 100644
--- a/browser/base/content/browser.js
+++ b/browser/base/content/browser.js
@@ -225,6 +225,11 @@ XPCOMUtils.defineLazyScriptGetter(
["DownloadsButton", "DownloadsIndicatorView"],
"chrome://browser/content/downloads/indicator.js"
);
+XPCOMUtils.defineLazyScriptGetter(
+ this,
+ ["SecurityLevelButton"],
+ "chrome://browser/content/securitylevel/securityLevel.js"
+);
XPCOMUtils.defineLazyScriptGetter(
this,
"gEditItemOverlay",
@@ -1796,6 +1801,9 @@ var gBrowserInit = {
// doesn't flicker as the window is being shown.
DownloadsButton.init();
+ // Init the SecuritySettingsButton
+ SecurityLevelButton.init();
+
// Certain kinds of automigration rely on this notification to complete
// their tasks BEFORE the browser window is shown. SessionStore uses it to
// restore tabs into windows AFTER important parts like gMultiProcessBrowser
@@ -2520,6 +2528,8 @@ var gBrowserInit = {
DownloadsButton.uninit();
+ SecurityLevelButton.uninit();
+
gAccessibilityServiceIndicator.uninit();
if (gToolbarKeyNavEnabled) {
diff --git a/browser/base/content/browser.xhtml b/browser/base/content/browser.xhtml
index 2a92da47f1aa..33af225f739b 100644
--- a/browser/base/content/browser.xhtml
+++ b/browser/base/content/browser.xhtml
@@ -20,6 +20,8 @@
<?xml-stylesheet href="chrome://browser/content/browser.css" type="text/css"?>
<?xml-stylesheet href="chrome://browser/content/tabbrowser.css" type="text/css"?>
<?xml-stylesheet href="chrome://browser/content/downloads/downloads.css" type="text/css"?>
+<?xml-stylesheet href="chrome://browser/content/securitylevel/securityLevelPanel.css"?>
+<?xml-stylesheet href="chrome://browser/content/securitylevel/securityLevelButton.css"?>
<?xml-stylesheet href="chrome://browser/content/places/places.css" type="text/css"?>
<?xml-stylesheet href="chrome://browser/content/usercontext/usercontext.css" type="text/css"?>
<?xml-stylesheet href="chrome://browser/skin/" type="text/css"?>
@@ -651,6 +653,7 @@
#include ../../components/controlcenter/content/protectionsPanel.inc.xhtml
#include ../../components/downloads/content/downloadsPanel.inc.xhtml
#include ../../../devtools/startup/enableDevToolsPopup.inc.xhtml
+#include ../../components/securitylevel/content/securityLevelPanel.inc.xhtml
#include browser-allTabsMenu.inc.xhtml
<tooltip id="dynamic-shortcut-tooltip"
@@ -2088,6 +2091,8 @@
</box>
</toolbarbutton>
+#include ../../components/securitylevel/content/securityLevelButton.inc.xhtml
+
<toolbarbutton id="fxa-toolbar-menu-button" class="toolbarbutton-1 chromeclass-toolbar-additional subviewbutton-nav"
badged="true"
onmousedown="gSync.toggleAccountPanel(this, event)"
diff --git a/browser/components/moz.build b/browser/components/moz.build
index 1e977cfe5499..1c421b761888 100644
--- a/browser/components/moz.build
+++ b/browser/components/moz.build
@@ -50,6 +50,7 @@ DIRS += [
"protocolhandler",
"resistfingerprinting",
"search",
+ "securitylevel",
"sessionstore",
"shell",
"syncedtabs",
diff --git a/browser/components/preferences/preferences.xhtml b/browser/components/preferences/preferences.xhtml
index aab4a9e558bc..10faf11bfecd 100644
--- a/browser/components/preferences/preferences.xhtml
+++ b/browser/components/preferences/preferences.xhtml
@@ -12,6 +12,7 @@
<?xml-stylesheet href="chrome://browser/skin/preferences/search.css"?>
<?xml-stylesheet href="chrome://browser/skin/preferences/containers.css"?>
<?xml-stylesheet href="chrome://browser/skin/preferences/privacy.css"?>
+<?xml-stylesheet href="chrome://browser/content/securitylevel/securityLevelPreferences.css"?>
<!DOCTYPE html>
diff --git a/browser/components/preferences/privacy.inc.xhtml b/browser/components/preferences/privacy.inc.xhtml
index 8737620b66d5..29179473aadd 100644
--- a/browser/components/preferences/privacy.inc.xhtml
+++ b/browser/components/preferences/privacy.inc.xhtml
@@ -907,6 +907,8 @@
<html:h1 data-l10n-id="security-header"/>
</hbox>
+#include ../securitylevel/content/securityLevelPreferences.inc.xhtml
+
<!-- addons, forgery (phishing) UI Security -->
<groupbox id="browsingProtectionGroup" data-category="panePrivacy" hidden="true">
<label><html:h2 data-l10n-id="security-browsing-protection"/></label>
diff --git a/browser/components/preferences/privacy.js b/browser/components/preferences/privacy.js
index 599bc3646d24..ad6ca85cf0aa 100644
--- a/browser/components/preferences/privacy.js
+++ b/browser/components/preferences/privacy.js
@@ -80,6 +80,12 @@ XPCOMUtils.defineLazyGetter(this, "AlertsServiceDND", function() {
}
});
+XPCOMUtils.defineLazyScriptGetter(
+ this,
+ ["SecurityLevelPreferences"],
+ "chrome://browser/content/securitylevel/securityLevel.js"
+);
+
XPCOMUtils.defineLazyServiceGetter(
this,
"listManager",
@@ -305,6 +311,18 @@ function setUpContentBlockingWarnings() {
var gPrivacyPane = {
_pane: null,
+ /**
+ * Show the Security Level UI
+ */
+ _initSecurityLevel() {
+ SecurityLevelPreferences.init();
+ let unload = () => {
+ window.removeEventListener("unload", unload);
+ SecurityLevelPreferences.uninit();
+ };
+ window.addEventListener("unload", unload);
+ },
+
/**
* Whether the prompt to restart Firefox should appear when changing the autostart pref.
*/
@@ -510,6 +528,7 @@ var gPrivacyPane = {
this.trackingProtectionReadPrefs();
this.networkCookieBehaviorReadPrefs();
this._initTrackingProtectionExtensionControl();
+ this._initSecurityLevel();
Services.telemetry.setEventRecordingEnabled("pwmgr", true);
diff --git a/browser/components/securitylevel/content/securityLevel.js b/browser/components/securitylevel/content/securityLevel.js
new file mode 100644
index 000000000000..b47d0cfb545e
--- /dev/null
+++ b/browser/components/securitylevel/content/securityLevel.js
@@ -0,0 +1,501 @@
+"use strict";
+
+ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm");
+ChromeUtils.import("resource://gre/modules/Services.jsm");
+
+XPCOMUtils.defineLazyModuleGetters(this, {
+ CustomizableUI: "resource:///modules/CustomizableUI.jsm",
+ PanelMultiView: "resource:///modules/PanelMultiView.jsm",
+});
+
+ChromeUtils.defineModuleGetter(
+ this,
+ "TorStrings",
+ "resource:///modules/TorStrings.jsm"
+);
+
+/*
+ Security Level Prefs
+
+ Getters and Setters for relevant torbutton prefs
+*/
+const SecurityLevelPrefs = {
+ security_slider_pref : "extensions.torbutton.security_slider",
+ security_custom_pref : "extensions.torbutton.security_custom",
+
+ get securitySlider() {
+ try {
+ return Services.prefs.getIntPref(this.security_slider_pref);
+ } catch(e) {
+ // init pref to 4 (standard)
+ const val = 4;
+ Services.prefs.setIntPref(this.security_slider_pref, val);
+ return val;
+ }
+ },
+
+ set securitySlider(val) {
+ Services.prefs.setIntPref(this.security_slider_pref, val);
+ },
+
+ get securityCustom() {
+ try {
+ return Services.prefs.getBoolPref(this.security_custom_pref);
+ } catch(e) {
+ // init custom to false
+ const val = false;
+ Services.prefs.setBoolPref(this.security_custom_pref, val);
+ return val;
+ }
+ },
+
+ set securityCustom(val) {
+ Services.prefs.setBoolPref(this.security_custom_pref, val);
+ },
+}; /* Security Level Prefs */
+
+/*
+ Security Level Button Code
+
+ Controls init and update of the security level toolbar button
+*/
+
+const SecurityLevelButton = {
+ _securityPrefsBranch : null,
+
+ _populateXUL : function(securityLevelButton) {
+ if (securityLevelButton != null) {
+ securityLevelButton.setAttribute("tooltiptext", TorStrings.securityLevel.securityLevel);
+ securityLevelButton.setAttribute("label", TorStrings.securityLevel.securityLevel);
+ }
+ },
+
+ _configUIFromPrefs : function(securityLevelButton) {
+ if (securityLevelButton != null) {
+ let securitySlider = SecurityLevelPrefs.securitySlider;
+ let classList = securityLevelButton.classList;
+ classList.remove("standard", "safer", "safest");
+ switch(securitySlider) {
+ case 4:
+ classList.add("standard");
+ securityLevelButton.setAttribute("tooltiptext", TorStrings.securityLevel.standard.tooltip);
+ break;
+ case 2:
+ classList.add("safer");
+ securityLevelButton.setAttribute("tooltiptext", TorStrings.securityLevel.safer.tooltip);
+ break;
+ case 1:
+ classList.add("safest");
+ securityLevelButton.setAttribute("tooltiptext", TorStrings.securityLevel.safest.tooltip);
+ break;
+ }
+ }
+ },
+
+ get button() {
+ let button = document.getElementById("security-level-button");
+ if (!button) {
+ return null;
+ }
+ return button;
+ },
+
+ get anchor() {
+ let anchor = this.button.icon;
+ if (!anchor) {
+ return null;
+ }
+
+ anchor.setAttribute("consumeanchor", SecurityLevelButton.button.id);
+ return anchor;
+ },
+
+ init : function() {
+ // set the initial class based off of the current pref
+ let button = this.button;
+ this._populateXUL(button);
+ this._configUIFromPrefs(button);
+
+ this._securityPrefsBranch = Services.prefs.getBranch("extensions.torbutton.");
+ this._securityPrefsBranch.addObserver("", this, false);
+
+ CustomizableUI.addListener(this);
+
+ SecurityLevelPanel.init();
+ },
+
+ uninit : function() {
+ CustomizableUI.removeListener(this);
+
+ this._securityPrefsBranch.removeObserver("", this);
+ this._securityPrefsBranch = null;
+
+ SecurityLevelPanel.uninit();
+ },
+
+ observe : function(subject, topic, data) {
+ switch(topic) {
+ case "nsPref:changed":
+ if (data == "security_slider") {
+ this._configUIFromPrefs(this.button);
+ }
+ break;
+ }
+ },
+
+ // callback for entering the 'Customize Firefox' screen to set icon
+ onCustomizeStart : function(window) {
+ let navigatorToolbox = document.getElementById("navigator-toolbox");
+ let button = navigatorToolbox.palette.querySelector("#security-level-button");
+ this._populateXUL(button);
+ this._configUIFromPrefs(button);
+ },
+
+ // callback when CustomizableUI modifies DOM
+ onWidgetAfterDOMChange : function(aNode, aNextNode, aContainer, aWasRemoval) {
+ if (aNode.id == "security-level-button" && !aWasRemoval) {
+ this._populateXUL(aNode);
+ this._configUIFromPrefs(aNode);
+ }
+ },
+
+ // for when the toolbar button needs to be activated and displays the Security Level panel
+ //
+ // In the toolbarbutton xul you'll notice we register this callback for both onkeypress and
+ // onmousedown. We do this to match the behavior of other panel spawning buttons such as Downloads,
+ // Library, and the Hamburger menus. Using oncommand alone would result in only getting fired
+ // after onclick, which is mousedown followed by mouseup.
+ onCommand : function(aEvent) {
+ // snippet stolen from /browser/components/downloads/indicator.js DownloadsIndicatorView.onCommand(evt)
+ if (
+ (aEvent.type == "mousedown" && aEvent.button != 0) ||
+ (aEvent.type == "keypress" && aEvent.key != " " && aEvent.key != "Enter")
+ ) {
+ return;
+ }
+
+ // we need to set this attribute for the button to be shaded correctly to look like it is pressed
+ // while the security level panel is open
+ this.button.setAttribute("open", "true");
+ SecurityLevelPanel.show();
+ },
+}; /* Security Level Button */
+
+/*
+ Security Level Panel Code
+
+ Controls init and update of the panel in the security level hanger
+*/
+
+const SecurityLevelPanel = {
+ _securityPrefsBranch : null,
+ _panel : null,
+ _anchor : null,
+ _populated : false,
+
+ _populateXUL : function() {
+ // get the panel elements we need to populate
+ let panelview = document.getElementById("securityLevel-panelview");
+ let labelHeader = panelview.querySelector("#securityLevel-header");
+ let labelCustomWarning = panelview.querySelector("#securityLevel-customWarning")
+ let labelLearnMore = panelview.querySelector("#securityLevel-learnMore");
+ let buttonRestoreDefaults = panelview.querySelector("#securityLevel-restoreDefaults");
+ let buttonAdvancedSecuritySettings = panelview.querySelector("#securityLevel-advancedSecuritySettings");
+
+ labelHeader.setAttribute("value", TorStrings.securityLevel.securityLevel);
+ labelCustomWarning.setAttribute("value", TorStrings.securityLevel.customWarning);
+ labelLearnMore.setAttribute("value", TorStrings.securityLevel.learnMore);
+ labelLearnMore.setAttribute("href", TorStrings.securityLevel.learnMoreURL);
+ buttonRestoreDefaults.setAttribute("label", TorStrings.securityLevel.restoreDefaults);
+ buttonAdvancedSecuritySettings.setAttribute("label", TorStrings.securityLevel.advancedSecuritySettings);
+
+ // rest of the XUL is set based on security prefs
+ this._configUIFromPrefs();
+
+ this._populated = true;
+ },
+
+ _configUIFromPrefs : function() {
+ // get security prefs
+ let securitySlider = SecurityLevelPrefs.securitySlider;
+ let securityCustom = SecurityLevelPrefs.securityCustom;
+
+ // get the panel elements we need to populate
+ let panelview = document.getElementById("securityLevel-panelview");
+ let labelLevel = panelview.querySelector("#securityLevel-level");
+ let labelCustomWarning = panelview.querySelector("#securityLevel-customWarning")
+ let summary = panelview.querySelector("#securityLevel-summary");
+ let buttonRestoreDefaults = panelview.querySelector("#securityLevel-restoreDefaults");
+ let buttonAdvancedSecuritySettings = panelview.querySelector("#securityLevel-advancedSecuritySettings");
+
+ // only visible when user is using custom settings
+ labelCustomWarning.hidden = !securityCustom;
+ buttonRestoreDefaults.hidden = !securityCustom;
+
+ // Descriptions change based on security level
+ switch(securitySlider) {
+ // standard
+ case 4:
+ labelLevel.setAttribute("value", TorStrings.securityLevel.standard.level);
+ summary.textContent = TorStrings.securityLevel.standard.summary;
+ break;
+ // safer
+ case 2:
+ labelLevel.setAttribute("value", TorStrings.securityLevel.safer.level);
+ summary.textContent = TorStrings.securityLevel.safer.summary;
+ break;
+ // safest
+ case 1:
+ labelLevel.setAttribute("value", TorStrings.securityLevel.safest.level);
+ summary.textContent = TorStrings.securityLevel.safest.summary;
+ break;
+ }
+
+ // override the summary text with custom warning
+ if (securityCustom) {
+ summary.textContent = TorStrings.securityLevel.custom.summary;
+ }
+ },
+
+ init : function() {
+ this._securityPrefsBranch = Services.prefs.getBranch("extensions.torbutton.");
+ this._securityPrefsBranch.addObserver("", this, false);
+ },
+
+ uninit : function() {
+ this._securityPrefsBranch.removeObserver("", this);
+ this._securityPrefsBranch = null;
+ },
+
+ show : function() {
+ // we have to defer this until after the browser has finished init'ing before
+ // we can populate the panel
+ if (!this._populated) {
+ this._populateXUL();
+ }
+
+ let panel = document.getElementById("securityLevel-panel");
+ panel.hidden = false;
+ PanelMultiView.openPopup(panel, SecurityLevelButton.anchor, "bottomcenter topright",
+ 0, 0, false, null).catch(Cu.reportError);
+ },
+
+ hide : function() {
+ let panel = document.getElementById("securityLevel-panel");
+ PanelMultiView.hidePopup(panel);
+ },
+
+ restoreDefaults : function() {
+ SecurityLevelPrefs.securityCustom = false;
+ // hide and reshow so that layout re-renders properly
+ this.hide();
+ this.show(this._anchor);
+ },
+
+ openAdvancedSecuritySettings : function() {
+ openPreferences("privacy-securitylevel");
+ this.hide();
+ },
+
+ // callback when prefs change
+ observe : function(subject, topic, data) {
+ switch(topic) {
+ case "nsPref:changed":
+ if (data == "security_slider" || data == "security_custom") {
+ this._configUIFromPrefs();
+ }
+ break;
+ }
+ },
+
+ // callback when the panel is displayed
+ onPopupShown : function(event) {
+ SecurityLevelButton.button.setAttribute("open", "true");
+ },
+
+ // callback when the panel is hidden
+ onPopupHidden : function(event) {
+ SecurityLevelButton.button.removeAttribute("open");
+ }
+}; /* Security Level Panel */
+
+/*
+ Security Level Preferences Code
+
+ Code to handle init and update of security level section in about:preferences#privacy
+*/
+
+const SecurityLevelPreferences =
+{
+ _securityPrefsBranch : null,
+
+ _populateXUL : function() {
+ let groupbox = document.getElementById("securityLevel-groupbox");
+
+ let labelHeader = groupbox.querySelector("#securityLevel-header");
+ labelHeader.textContent = TorStrings.securityLevel.securityLevel;
+
+ let spanOverview = groupbox.querySelector("#securityLevel-overview");
+ spanOverview.textContent = TorStrings.securityLevel.overview;
+
+ let labelLearnMore = groupbox.querySelector("#securityLevel-learnMore");
+ labelLearnMore.setAttribute("value", TorStrings.securityLevel.learnMore);
+ labelLearnMore.setAttribute("href", TorStrings.securityLevel.learnMoreURL);
+
+ let radiogroup = document.getElementById("securityLevel-radiogroup");
+ radiogroup.addEventListener("command", SecurityLevelPreferences.selectSecurityLevel);
+
+ let populateRadioElements = function(vboxQuery, stringStruct) {
+ let vbox = groupbox.querySelector(vboxQuery);
+
+ let radio = vbox.querySelector("radio");
+ radio.setAttribute("label", stringStruct.level);
+
+ let customWarning = vbox.querySelector("#securityLevel-customWarning");
+ customWarning.setAttribute("value", TorStrings.securityLevel.customWarning);
+
+ let labelSummary = vbox.querySelector("#securityLevel-summary");
+ labelSummary.textContent = stringStruct.summary;
+
+ let labelRestoreDefaults = vbox.querySelector("#securityLevel-restoreDefaults");
+ labelRestoreDefaults.setAttribute("value", TorStrings.securityLevel.restoreDefaults);
+ labelRestoreDefaults.addEventListener("click", SecurityLevelPreferences.restoreDefaults);
+
+ let description1 = vbox.querySelector("#securityLevel-description1");
+ if (description1) {
+ description1.textContent = stringStruct.description1;
+ }
+ let description2 = vbox.querySelector("#securityLevel-description2");
+ if (description2) {
+ description2.textContent = stringStruct.description2;
+ }
+ let description3 = vbox.querySelector("#securityLevel-description3");
+ if (description3) {
+ description3.textContent = stringStruct.description3;
+ }
+ };
+
+ populateRadioElements("#securityLevel-vbox-standard", TorStrings.securityLevel.standard);
+ populateRadioElements("#securityLevel-vbox-safer", TorStrings.securityLevel.safer);
+ populateRadioElements("#securityLevel-vbox-safest", TorStrings.securityLevel.safest);
+ },
+
+ _configUIFromPrefs : function() {
+ // read our prefs
+ let securitySlider = SecurityLevelPrefs.securitySlider;
+ let securityCustom = SecurityLevelPrefs.securityCustom;
+
+ // get our elements
+ let groupbox = document.getElementById("securityLevel-groupbox");
+
+ let radiogroup = groupbox.querySelector("#securityLevel-radiogroup");
+ let labelStandardCustom = groupbox.querySelector("#securityLevel-vbox-standard label#securityLevel-customWarning");
+ let labelSaferCustom = groupbox.querySelector("#securityLevel-vbox-safer label#securityLevel-customWarning");
+ let labelSafestCustom = groupbox.querySelector("#securityLevel-vbox-safest label#securityLevel-customWarning");
+ let labelStandardRestoreDefaults = groupbox.querySelector("#securityLevel-vbox-standard label#securityLevel-restoreDefaults");
+ let labelSaferRestoreDefaults = groupbox.querySelector("#securityLevel-vbox-safer label#securityLevel-restoreDefaults");
+ let labelSafestRestoreDefaults = groupbox.querySelector("#securityLevel-vbox-safest label#securityLevel-restoreDefaults");
+
+ // hide custom label by default until we know which level we're at
+ labelStandardCustom.hidden = true;
+ labelSaferCustom.hidden = true;
+ labelSafestCustom.hidden = true;
+
+ labelStandardRestoreDefaults.hidden = true;
+ labelSaferRestoreDefaults.hidden = true;
+ labelSafestRestoreDefaults.hidden = true;
+
+ switch(securitySlider) {
+ // standard
+ case 4:
+ radiogroup.value = "standard";
+ labelStandardCustom.hidden = !securityCustom;
+ labelStandardRestoreDefaults.hidden = !securityCustom;
+ break;
+ // safer
+ case 2:
+ radiogroup.value = "safer";
+ labelSaferCustom.hidden = !securityCustom;
+ labelSaferRestoreDefaults.hidden = !securityCustom;
+ break;
+ // safest
+ case 1:
+ radiogroup.value = "safest";
+ labelSafestCustom.hidden = !securityCustom;
+ labelSafestRestoreDefaults.hidden = !securityCustom;
+ break;
+ }
+ },
+
+ init : function() {
+ // populate XUL with localized strings
+ this._populateXUL();
+
+ // read prefs and populate UI
+ this._configUIFromPrefs();
+
+ // register for pref chagnes
+ this._securityPrefsBranch = Services.prefs.getBranch("extensions.torbutton.");
+ this._securityPrefsBranch.addObserver("", this, false);
+ },
+
+ uninit : function() {
+ // unregister for pref change events
+ this._securityPrefsBranch.removeObserver("", this);
+ this._securityPrefsBranch = null;
+ },
+
+ // callback for when prefs change
+ observe : function(subject, topic, data) {
+ switch(topic) {
+ case "nsPref:changed":
+ if (data == "security_slider" ||
+ data == "security_custom") {
+ this._configUIFromPrefs();
+ }
+ break;
+ }
+ },
+
+ selectSecurityLevel : function() {
+ // radio group elements
+ let radiogroup = document.getElementById("securityLevel-radiogroup");
+
+ // update pref based on selected radio option
+ switch (radiogroup.value) {
+ case "standard":
+ SecurityLevelPrefs.securitySlider = 4;
+ break;
+ case "safer":
+ SecurityLevelPrefs.securitySlider = 2;
+ break;
+ case "safest":
+ SecurityLevelPrefs.securitySlider = 1;
+ break;
+ }
+
+ SecurityLevelPreferences.restoreDefaults();
+ },
+
+ restoreDefaults : function() {
+ SecurityLevelPrefs.securityCustom = false;
+ },
+}; /* Security Level Prefereces */
+
+Object.defineProperty(this, "SecurityLevelButton", {
+ value: SecurityLevelButton,
+ enumerable: true,
+ writable: false
+});
+
+Object.defineProperty(this, "SecurityLevelPanel", {
+ value: SecurityLevelPanel,
+ enumerable: true,
+ writable: false
+});
+
+Object.defineProperty(this, "SecurityLevelPreferences", {
+ value: SecurityLevelPreferences,
+ enumerable: true,
+ writable: false
+});
diff --git a/browser/components/securitylevel/content/securityLevelButton.css b/browser/components/securitylevel/content/securityLevelButton.css
new file mode 100644
index 000000000000..81f2365bae28
--- /dev/null
+++ b/browser/components/securitylevel/content/securityLevelButton.css
@@ -0,0 +1,9 @@
+toolbarbutton#security-level-button.standard {
+ list-style-image: url("chrome://browser/content/securitylevel/securityLevelButton.svg#standard");
+}
+toolbarbutton#security-level-button.safer {
+ list-style-image: url("chrome://browser/content/securitylevel/securityLevelButton.svg#safer");
+}
+toolbarbutton#security-level-button.safest {
+ list-style-image: url("chrome://browser/content/securitylevel/securityLevelButton.svg#safest");
+}
diff --git a/browser/components/securitylevel/content/securityLevelButton.inc.xhtml b/browser/components/securitylevel/content/securityLevelButton.inc.xhtml
new file mode 100644
index 000000000000..96ee1ec0ca49
--- /dev/null
+++ b/browser/components/securitylevel/content/securityLevelButton.inc.xhtml
@@ -0,0 +1,7 @@
+<toolbarbutton id="security-level-button" class="toolbarbutton-1 chromeclass-toolbar-additional"
+ badged="true"
+ removable="true"
+ onmousedown="SecurityLevelButton.onCommand(event);"
+ onkeypress="SecurityLevelButton.onCommand(event);"
+ closemenu="none"
+ cui-areatype="toolbar"/>
diff --git a/browser/components/securitylevel/content/securityLevelButton.svg b/browser/components/securitylevel/content/securityLevelButton.svg
new file mode 100644
index 000000000000..8535cdcc531e
--- /dev/null
+++ b/browser/components/securitylevel/content/securityLevelButton.svg
@@ -0,0 +1,21 @@
+<svg width="14px" height="16px" viewBox="0 0 14 16" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+ <style>
+ use:not(:target) {
+ display: none;
+ }
+ </style>
+ <defs>
+ <g id="standard_icon" stroke="none" stroke-width="1">
+ <path d="M7.0 2.16583509C7.0 2.16583509 2.0 4.24375717 2.0 4.24375717C2.0 4.24375717 2.0 7.27272727 2.0 7.27272727C2.0 10.2413541 4.13435329 13.0576771 7.0 13.9315843C9.8656467 13.0576771 12.0 10.2413541 12.0 7.27272727C12.0 7.27272727 12.0 4.24375717 12.0 4.24375717C12.0 4.24375717 7.0 2.16583509 7.0 2.16583509C7.0 2.16583509 7.0 2.16583509 7.0 2.16583509M7.0 0.0C7.0 0.0 14.0 2.90909091 14.0 2.90909091C14.0 2.90909091 14.0 7.27272727 14.0 7.27272727C14.0 11.3090909 11.0133333 15.0836364 7.0 16.0C2.98666667 15.0836364 0.0 11.3090909 0.0 7.27272727C0.0 7.27272727 0.0 2.90909091 0.0 2.90909091C0.0 2.90909091 7.0 0.0 7.0 0.0C7.0 0.0 7.0 0.0 7.0 0.0" />
+ </g>
+ <g id="safer_icon" stroke="none" stroke-width="1">
+ <path fill-rule="nonzero" d="M7.0 2.1658351C7.0 13.931584 7.0 2.1658351 7.0 13.931584C9.8656467 13.057677 12.0 10.241354 12.0 7.2727273C12.0 7.2727273 12.0 4.2437572 12.0 4.2437572C12.0 4.2437572 7.0 2.1658351 7.0 2.1658351C7.0 2.1658351 7.0 2.1658351 7.0 2.1658351M7.0 0.0C7.0 0.0 14.0 2.9090909 14.0 2.9090909C14.0 2.9090909 14.0 7.2727273 14.0 7.2727273C14.0 11.309091 11.013333 15.083636 7.0 16.0C2.9866667 15.083636 0.0 11.309091 0.0 7.2727273C0.0 7.2727273 0.0 2.9090909 0.0 2.9090909C0.0 2.9090909 7.0 0.0 7.0 0.0"/>
+ </g>
+ <g id="safest_icon" stroke="none" stroke-width="1">
+ <path d="M7.0 0.0C7.0 0.0 14.0 2.90909091 14.0 2.90909091C14.0 2.90909091 14.0 7.27272727 14.0 7.27272727C14.0 11.3090909 11.0133333 15.0836364 7.0 16.0C2.98666667 15.0836364 0.0 11.3090909 0.0 7.27272727C0.0 7.27272727 0.0 2.90909091 0.0 2.90909091C0.0 2.90909091 7.0 0.0 7.0 0.0C7.0 0.0 7.0 0.0 7.0 0.0" />
+ </g>
+ </defs>
+ <use id="standard" fill="context-fill" fill-opacity="context-fill-opacity" href="#standard_icon" />
+ <use id="safer" fill="context-fill" fill-opacity="context-fill-opacity" href="#safer_icon" />
+ <use id="safest" fill="context-fill" fill-opacity="context-fill-opacity" href="#safest_icon" />
+</svg>
diff --git a/browser/components/securitylevel/content/securityLevelPanel.css b/browser/components/securitylevel/content/securityLevelPanel.css
new file mode 100644
index 000000000000..70022e2bd4b2
--- /dev/null
+++ b/browser/components/securitylevel/content/securityLevelPanel.css
@@ -0,0 +1,82 @@
+/* Security Level CSS */
+
+panel#securityLevel-panel > .panel-arrowcontainer > .panel-arrowcontent {
+ padding: 0;
+}
+
+panelview#securityLevel-panelview {
+ width: 20em;
+}
+
+panelview#securityLevel-panelview>vbox.panel-subview-body {
+ padding: 1em;
+}
+
+label#securityLevel-header {
+ text-transform: uppercase;
+ color: var(--panel-disabled-color);
+ font-size: 0.85em;
+ margin: 0 0 0.4em 0;
+ padding: 0;
+}
+
+hbox#securityLevel-levelHbox {
+ margin-bottom: 1em;
+}
+
+label#securityLevel-level {
+ font-size: 1.5em;
+ margin: 0 0.5em 0 0;
+ padding: 0;
+}
+
+label#securityLevel-customWarning {
+ border-radius: 2px;
+ background-color: #ffe845;
+ text-transform: uppercase;
+ font-weight: bolder;
+ font-size: 0.8em;
+ height: 1em;
+ line-height: 1em;
+ vertical-align: middle;
+ margin: auto;
+ padding: 0.4em;
+}
+
+panelview#securityLevel-panelview description {
+ margin: 0 -0.5em 0.5em 0;
+ padding: 0 !important;
+}
+
+label#securityLevel-learnMore {
+ margin: 0 0 1.0em 0;
+ padding: 0;
+}
+
+panelview#securityLevel-panelview button {
+ -moz-appearance: none;
+ background-color: var(--arrowpanel-dimmed);
+}
+
+panelview#securityLevel-panelview button:hover {
+ background-color: var(--arrowpanel-dimmed-further);
+}
+
+panelview#securityLevel-panelview button:active {
+ background-color: var(--arrowpanel-dimmed-even-further);
+}
+
+button#securityLevel-restoreDefaults {
+ margin: 0 0 1.0em 0;
+ padding: 0.45em;
+ color: inherit !important;
+}
+
+button#securityLevel-advancedSecuritySettings {
+ margin: 0 -1.0em -1.0em -1.0em;
+ border-radius: 0;
+ border-top: 1px solid var(--panel-separator-color);
+ padding: 0;
+ height: 3.0em;
+ color: inherit !important;
+}
diff --git a/browser/components/securitylevel/content/securityLevelPanel.inc.xhtml b/browser/components/securitylevel/content/securityLevelPanel.inc.xhtml
new file mode 100644
index 000000000000..4abbb12dd856
--- /dev/null
+++ b/browser/components/securitylevel/content/securityLevelPanel.inc.xhtml
@@ -0,0 +1,38 @@
+<panel id="securityLevel-panel"
+ role="group"
+ type="arrow"
+ orient="vertical"
+ level="top"
+ hidden="true"
+ class="panel-no-padding"
+ onpopupshown="SecurityLevelPanel.onPopupShown(event);"
+ onpopuphidden="SecurityLevelPanel.onPopupHidden(event);"
+ >
+ <panelmultiview mainViewId="securityLevel-panelview">
+ <panelview id="securityLevel-panelview" descriptionheightworkaround="true">
+ <vbox class="panel-subview-body">
+ <label id="securityLevel-header"/>
+ <hbox id="securityLevel-levelHbox">
+ <label id="securityLevel-level"/>
+ <vbox>
+ <spacer flex="1"/>
+ <label id="securityLevel-customWarning"/>
+ <spacer flex="1"/>
+ </vbox>
+ </hbox>
+ <description id="securityLevel-summary"/>
+ <label
+ id="securityLevel-learnMore"
+ class="learnMore text-link"
+ onclick="SecurityLevelPanel.hide();"
+ is="text-link"/>
+ <button
+ id="securityLevel-restoreDefaults"
+ oncommand="SecurityLevelPanel.restoreDefaults();"/>
+ <button
+ id="securityLevel-advancedSecuritySettings"
+ oncommand="SecurityLevelPanel.openAdvancedSecuritySettings();"/>
+ </vbox>
+ </panelview>
+ </panelmultiview>
+</panel>
diff --git a/browser/components/securitylevel/content/securityLevelPreferences.css b/browser/components/securitylevel/content/securityLevelPreferences.css
new file mode 100644
index 000000000000..0d1040d177d8
--- /dev/null
+++ b/browser/components/securitylevel/content/securityLevelPreferences.css
@@ -0,0 +1,26 @@
+label#securityLevel-customWarning {
+ border-radius: 2px;
+ background-color: #ffe845;
+ text-transform: uppercase;
+ font-weight: bolder;
+ font-size: 0.7em;
+ height: 1em;
+ line-height: 1em;
+ padding: 0.35em;
+}
+
+radiogroup#securityLevel-radiogroup radio {
+ font-weight: bold;
+}
+
+vbox#securityLevel-vbox-standard,
+vbox#securityLevel-vbox-safer,
+vbox#securityLevel-vbox-safest {
+ margin-top: 0.4em;
+}
+
+vbox#securityLevel-vbox-standard description.indent,
+vbox#securityLevel-vbox-safer description.indent,
+vbox#securityLevel-vbox-safest description.indent {
+ margin-inline-start: 0 !important;
+}
diff --git a/browser/components/securitylevel/content/securityLevelPreferences.inc.xhtml b/browser/components/securitylevel/content/securityLevelPreferences.inc.xhtml
new file mode 100644
index 000000000000..a108d44a7b51
--- /dev/null
+++ b/browser/components/securitylevel/content/securityLevelPreferences.inc.xhtml
@@ -0,0 +1,62 @@
+<groupbox id="securityLevel-groupbox" data-category="panePrivacy" hidden="true">
+ <label><html:h2 id="securityLevel-header"/></label>
+ <vbox data-subcategory="securitylevel" flex="1">
+ <description flex="1">
+ <html:span id="securityLevel-overview" class="tail-with-learn-more"/>
+ <label id="securityLevel-learnMore" class="learnMore text-link" is="text-link"/>
+ </description>
+ <radiogroup id="securityLevel-radiogroup">
+ <vbox id="securityLevel-vbox-standard">
+ <hbox>
+ <radio value="standard"/>
+ <vbox>
+ <spacer flex="1"/>
+ <label id="securityLevel-customWarning"/>
+ <spacer flex="1"/>
+ </vbox>
+ </hbox>
+ <description flex="1">
+ <html:span id="securityLevel-summary" class="tail-with-learn-more"/>
+ <label id="securityLevel-restoreDefaults"
+ class="learnMore text-link"/>
+ </description>
+ </vbox>
+ <vbox id="securityLevel-vbox-safer">
+ <hbox>
+ <radio value="safer"/>
+ <vbox>
+ <spacer flex="1"/>
+ <label id="securityLevel-customWarning"/>
+ <spacer flex="1"/>
+ </vbox>
+ </hbox>
+ <description flex="1">
+ <html:span id="securityLevel-summary" class="tail-with-learn-more"/>
+ <label id="securityLevel-restoreDefaults"
+ class="learnMore text-link"/>
+ </description>
+ <description id="securityLevel-description1" class="indent tip-caption"/>
+ <description id="securityLevel-description2" class="indent tip-caption"/>
+ <description id="securityLevel-description3" class="indent tip-caption"/>
+ </vbox>
+ <vbox id="securityLevel-vbox-safest">
+ <hbox>
+ <radio value="safest"/>
+ <vbox>
+ <spacer flex="1"/>
+ <label id="securityLevel-customWarning"/>
+ <spacer flex="1"/>
+ </vbox>
+ </hbox>
+ <description flex="1">
+ <html:span id="securityLevel-summary" class="tail-with-learn-more"/>
+ <label id="securityLevel-restoreDefaults"
+ class="learnMore text-link"/>
+ </description>
+ <description id="securityLevel-description1" class="indent tip-caption"/>
+ <description id="securityLevel-description2" class="indent tip-caption"/>
+ <description id="securityLevel-description3" class="indent tip-caption"/>
+ </vbox>
+ </radiogroup>
+ </vbox>
+</groupbox>
diff --git a/browser/components/securitylevel/jar.mn b/browser/components/securitylevel/jar.mn
new file mode 100644
index 000000000000..9ac408083fbc
--- /dev/null
+++ b/browser/components/securitylevel/jar.mn
@@ -0,0 +1,6 @@
+browser.jar:
+ content/browser/securitylevel/securityLevel.js (content/securityLevel.js)
+ content/browser/securitylevel/securityLevelPanel.css (content/securityLevelPanel.css)
+ content/browser/securitylevel/securityLevelButton.css (content/securityLevelButton.css)
+ content/browser/securitylevel/securityLevelPreferences.css (content/securityLevelPreferences.css)
+ content/browser/securitylevel/securityLevelButton.svg (content/securityLevelButton.svg)
diff --git a/browser/components/securitylevel/moz.build b/browser/components/securitylevel/moz.build
new file mode 100644
index 000000000000..2661ad7cb9f3
--- /dev/null
+++ b/browser/components/securitylevel/moz.build
@@ -0,0 +1 @@
+JAR_MANIFESTS += ["jar.mn"]
1
0