Version in base suite: 4.3-1 Base version: tbsync_4.3-1 Target version: tbsync_4.7-1~deb12u1 Base file: /srv/ftp-master.debian.org/ftp/pool/main/t/tbsync/tbsync_4.3-1.dsc Target file: /srv/ftp-master.debian.org/policy/pool/main/t/tbsync/tbsync_4.7-1~deb12u1.dsc _locales/bg/messages.json | 8 _locales/cs/messages.json | 8 _locales/de/messages.json | 92 +-- _locales/en-US/messages.json | 8 _locales/es/messages.json | 8 _locales/et/messages.json | 8 _locales/fr/messages.json | 8 _locales/gl/messages.json | 10 _locales/hu/messages.json | 8 _locales/it/messages.json | 8 _locales/ja/messages.json | 8 _locales/ko/messages.json | 8 _locales/pl/messages.json | 8 _locales/pt_BR/messages.json | 8 _locales/ro/messages.json | 8 _locales/ru/messages.json | 8 _locales/sv/messages.json | 8 content/api/BootstrapLoader/CHANGELOG.md | 15 content/api/BootstrapLoader/implementation.js | 676 ++++++++++++++++++++------ content/api/BootstrapLoader/schema.json | 4 content/manager/accounts.js | 12 content/manager/accounts.xhtml | 4 content/manager/editAccount.js | 3 content/manager/editAccount.xhtml | 7 content/manager/eventlog/eventlog.js | 9 content/manager/eventlog/eventlog.xhtml | 14 content/modules/db.js | 13 content/modules/io.js | 4 content/modules/lightning.js | 2 content/modules/manager.js | 11 content/passwordPrompt/passwordPrompt.css | 13 content/passwordPrompt/passwordPrompt.js | 8 content/passwordPrompt/passwordPrompt.xhtml | 44 - content/tbsync.jsm | 3 debian/changelog | 26 + debian/control | 6 debian/gbp.conf | 2 manifest.json | 4 38 files changed, 817 insertions(+), 285 deletions(-) diff -Nru tbsync-4.3/_locales/bg/messages.json tbsync-4.7/_locales/bg/messages.json --- tbsync-4.3/_locales/bg/messages.json 2022-10-12 19:40:25.000000000 +0000 +++ tbsync-4.7/_locales/bg/messages.json 2023-08-29 20:22:49.000000000 +0000 @@ -355,5 +355,11 @@ }, "toolbar.tooltiptext": { "message": "Синхронизирай информацията от всички TbSync регистрации със сървърите" + }, + "password.ok": { + "message": "ОК" + }, + "password.cancel": { + "message": "Отказ" } -} \ No newline at end of file +} diff -Nru tbsync-4.3/_locales/cs/messages.json tbsync-4.7/_locales/cs/messages.json --- tbsync-4.3/_locales/cs/messages.json 2022-10-12 19:40:25.000000000 +0000 +++ tbsync-4.7/_locales/cs/messages.json 2023-08-29 20:22:49.000000000 +0000 @@ -355,5 +355,11 @@ }, "toolbar.tooltiptext": { "message": "Synchronizovat poslední změny" + }, + "password.ok": { + "message": "OK" + }, + "password.cancel": { + "message": "Zrušit" } -} \ No newline at end of file +} diff -Nru tbsync-4.3/_locales/de/messages.json tbsync-4.7/_locales/de/messages.json --- tbsync-4.3/_locales/de/messages.json 2022-10-12 19:40:25.000000000 +0000 +++ tbsync-4.7/_locales/de/messages.json 2023-08-29 20:22:49.000000000 +0000 @@ -3,28 +3,28 @@ "message": "Um diesen Fehler zu beheben, können Sie einen Fehlerbericht an den Entwickler von TbSync schicken. Soll der Fehlerbericht jetzt angefertigt werden?" }, "NoDebugLog": { - "message": "Es liegen keine aussagekräftigen Debug-Meldungen vor. Bitte aktivieren Sie den Debug-Modus, starten Thunderbird neu und wiederholen dann alle Schritte um das fehlerhafte Verhalten zu reproduzieren." + "message": "Es liegen keine aussagekräftigen Debug-Meldungen vor. Bitte aktivieren Sie den Debug-Modus, starten Thunderbird neu und wiederholen dann alle Schritte, um das fehlerhafte Verhalten zu reproduzieren." }, "OopsMessage": { - "message": "Oops! TbSync konnte nicht starten!" + "message": "Hoppla! TbSync konnte nicht starten!" }, "RestartThunderbirdAndTryAgain": { - "message": "Der TbSync Debug-Modus wurde aktiviert, bitte starten Sie Thunderbird neu und versuchen Sie dann noch einmal TbSync zu öffnen." + "message": "Das TbSync-Debug-Protokoll wurde eingeschaltet. Bitte starten Sie Thunderbird neu, und versuchen Sie dann noch einmal, TbSync zu öffnen!" }, "UnableToTraceError": { - "message": "Es ist im Augenblick nicht möglich, diesen Fehler zu untersuchen, da der TbSync Debug-Modus nicht aktiviert ist. Soll der Debug-Modus aktiviert werden, damit dieser Fehler untersucht und behoben werden kann?" + "message": "Dieser Fehler kann nicht untersucht werden, solange das Debug-Protokoll deaktiviert ist. Soll das Protokoll jetzt aktiviert werden, damit dieser Fehler untersucht und behoben werden kann?" }, "accountacctions.delete": { - "message": "Konto '##accountname##' löschen" + "message": "Konto „##accountname##” löschen" }, "accountacctions.disable": { "message": "Konto '##accountname##' deaktivieren" }, "accountacctions.enable": { - "message": "Konto '##accountname##' aktivieren & Server kontaktieren" + "message": "Konto „##accountname##” aktivieren und Server kontaktieren" }, "accountacctions.sync": { - "message": "Konto '##accountname##' synchronisieren" + "message": "Konto „##accountname##” synchronisieren" }, "addressbook.searchall": { "message": "Alle Adressbücher durchsuchen" @@ -60,25 +60,25 @@ "message": "Leerlauf" }, "installProvider.header": { - "message": "Provider '##replace.1##' für TbSync ist noch nicht installiert." + "message": "Provider „##replace.1##” für TbSync ist noch nicht installiert." }, "manager.AccountActions": { - "message": "Konto Aktionen" + "message": "Konto-Aktionen" }, "manager.AddAccount": { - "message": "Neues Konto hinzufügen" + "message": "Konto hinzufügen" }, "manager.DeleteAccount": { - "message": "Konto löschen" + "message": "Konto entfernen" }, "manager.DisableAccount": { "message": "Konto deaktivieren" }, "manager.EnableAccount": { - "message": "Konto aktivieren & mit dem Server verbinden" + "message": "Konto aktivieren und mit dem Server verbinden" }, "manager.RetryConnectAccount": { - "message": "Erneut versuchen mit dem Server zu verbinden" + "message": "Erneut versuchen, mit dem Server zu verbinden" }, "manager.ShowEventLog": { "message": "Ereignisprotokoll anzeigen" @@ -96,10 +96,10 @@ "message": "Kontoeinstellungen" }, "manager.catman.text": { - "message": "TbSync synchronisiert auch Kontaktkategorien, die einen effizienten Ersatz für die nicht synchronisierbaren Kontaktlisten darstellen. Um diese im Thunderbird Adressbuch zu nutzen, können Sie das Add-On 'Category Manager' installieren. Dieses Add-On ermöglicht die Verwaltung überlappender kategoriebasierter Kontaktgruppen und stellt eine Reihe anderer kategoriespezifischer Funktionen bereit. Es kann aus dem offiziellen Mozilla Add-On Repository heruntergeladen werden:" + "message": "TbSync synchronisiert auch Kontaktkategorien, die einen effizienten Ersatz für die nicht synchronisierbaren Kontaktlisten darstellen. Um diese im Thunderbird-Adressbuch zu nutzen, können Sie das Add-On „Category Manager” installieren. Dieses Add-On ermöglicht die Verwaltung überlappender kategoriebasierter Kontaktgruppen und stellt eine Reihe anderer kategoriespezifischer Funktionen bereit. Es kann aus dem offiziellen Mozilla Add-On Repository heruntergeladen werden:" }, "manager.community": { - "message": "Community" + "message": "Nutzergemeinschaft" }, "manager.connecting": { "message": "Verbindung wird hergestellt" @@ -120,7 +120,7 @@ "message": "Aktiviert: Protokolliert alle Fehler" }, "manager.help.debuglevel.2": { - "message": "Aktiviert: Protokolliert alle gesendeten & empfangenen Daten" + "message": "Aktiviert: Protokolliert alle gesendeten und empfangenen Daten" }, "manager.help.debuglevel.3": { "message": "Aktiviert: Protokolliert alle Daten und einige interne Debug-Werte" @@ -138,25 +138,25 @@ "message": "Benötigen Sie Hilfe?" }, "manager.help.viewdebuglog": { - "message": "Debug-Log anzeigen" + "message": "Debug-Protokoll anzeigen" }, "manager.help.wiki": { - "message": "Besuchen Sie die Wikiseiten des TbSync Projektes, diese beinhalten zusätzliche Informationen, Benutzeranleitungen und detaillierte Konfigurationsbeschreibungen." + "message": "Besuchen Sie die Wikiseiten des TbSync-Projekts, diese enthalten zusätzliche Informationen, Benutzeranleitungen und detaillierte Konfigurationsbeschreibungen." }, "manager.installprovider.link": { - "message": "Klicken Sie auf den folgenden Link, um die Informationsseite des fehlenden Provider aufzurufen. Auf dieser Seite finden Sie weitere Informationen zu dem Provider und haben die Möglichkeit, diesen zu installieren:" + "message": "Klicken Sie auf den folgenden Link, um die Informationsseite des fehlenden Synchronisations-Providers aufzurufen. Dort finden Sie weitere Informationen dazu und haben die Möglichkeit, diesen zu installieren:" }, "manager.installprovider.warning": { - "message": "Dieser Provider stammt nicht aus dem offiziellen Thunderbird Add-On Verzeichnis und wurde demnach nicht von Thunderbird-Mitarbeitern überprüft. Dieser Provider könnte schlimme Dinge mit Ihrem System anstellen. Benutzung auf eigene Gefahr." + "message": "Dieser Provider stammt nicht aus der offiziellen Thunderbird-Add-On-Sammlung und wurde demnach nicht von Thunderbird-Mitarbeitern überprüft. Es könnte sich um Schad-Software handeln, deshalb verwenden Sie es auf eigene Gefahr." }, "manager.lockedsettings.description": { "message": "Um Synchronisierungsfehler zu vermeiden, können einige Einstellungen nicht bearbeitet werden, während das Konto aktiviert ist." }, "manager.missingprovider": { - "message": "Dieses Konto benötigt den ##provider## Synchronisationsprovider, der zur Zeit aber nicht installiert ist." + "message": "Dieses Konto benötigt den ##provider##-Synchronisations-Provider, noch nicht installiert ist." }, "manager.noaccounts": { - "message": "Es sind aktuell noch keine Konten konfiguriert." + "message": "Es sind noch keine Konten definiert." }, "manager.provider": { "message": "Provider installieren" @@ -174,13 +174,13 @@ "message": "Status" }, "manager.supporter.contributors": { - "message": "Mitwirkende & Übersetzer" + "message": "Mitwirkende und Übersetzer" }, "manager.supporter.details": { "message": "Details" }, "manager.supporter.sponsors": { - "message": "Sponsoren von Test-Accounts" + "message": "Sponsoren von Testkonten" }, "manager.tabs.status": { "message": "Synchronisationsstatus" @@ -195,7 +195,7 @@ "message": "Allgemein" }, "manager.tabs.status.never": { - "message": "Eine Einstellung von 0 deaktiviert periodische Synchronisation. Push Synchronisation wird noch nicht unterstützt." + "message": "Eine Einstellung von 0 deaktiviert periodische Synchronisation. Push-Synchronisation wird noch nicht unterstützt." }, "manager.tabs.status.resources": { "message": "Verfügbare Ressourcen" @@ -207,13 +207,13 @@ "message": "Jetzt synchronisieren" }, "manager.tabs.status.tryagain": { - "message": "Erneut versuchen mit dem Server zu verbinden" + "message": "Erneut versuchen, mit dem Server zu verbinden" }, "manager.title": { "message": "TbSync Kontoverwaltung" }, "manager.tryagain": { - "message": "Erneut versuchen mit dem Server zu verbinden" + "message": "Erneut versuchen, mit dem Server zu verbinden" }, "menu.settingslabel": { "message": "Synchronisationseinstellungen (TbSync)" @@ -228,13 +228,13 @@ "message": "Passwort:" }, "password.title": { - "message": "TbSync Anmeldeinformationen" + "message": "TbSync-Anmeldeinformationen" }, "password.user": { - "message": "Benutzer:" + "message": "Nutzer:" }, "popup.opensettings": { - "message": "TbSync Kontoverwaltung öffnen" + "message": "TbSync-Kontoverwaltung öffnen" }, "prompt.DeleteAccount": { "message": "Sind Sie sicher, dass Sie das Konto ##accountName## löschen möchten?" @@ -243,37 +243,37 @@ "message": "Sind Sie sicher, dass Sie dieses Konto deaktivieren möchten? Alle lokalen Veränderungen, die noch nicht synchronisiert wurden, gehen dabei verloren!" }, "prompt.Erase": { - "message": "Sind Sie sicher, dass Sie dieses Konto eines unbekannten Providers aus der Kontoliste entfernen möchten?" + "message": "Sind Sie sicher, dass Sie dieses Konto eines unbekannten Anbieters aus der Kontoliste entfernen möchten?" }, "prompt.Unsubscribe": { "message": "Sind Sie sicher, dass Sie dieses Element nicht länger abonnieren möchten? Alle lokalen Veränderungen, die noch nicht synchronisiert wurden, gehen dabei verloren!" }, "status.JavaScriptError": { - "message": "Javascript Fehler! Bitte prüfen Sie das Ereignisprotokoll für weitere Details." + "message": "Javascript-Fehler! Bitte prüfen Sie das Ereignisprotokoll für weitere Details!" }, "status.OAuthAbortError": { - "message": "OAuth 2.0 Authentifizierungsprozess vom Benutzer abgebrochen." + "message": "OAuth 2.0-Authentifizierungsprozess vom Nutzer abgebrochen." }, "status.OAuthHttpError": { - "message": "OAuth 2.0 Authentifizierungsprozess fehlgeschlagen (HTTP Error ##replace.1##)." + "message": "OAuth-2.0-Authentifizierungsprozess fehlgeschlagen (HTTP Error ##replace.1##)." }, "status.OAuthNetworkError": { - "message": "Verbindung zum OAuth 2.0 Authentifizierungsserver nicht möglich." + "message": "Verbindung zum OAuth-2.0-Authentifizierungsserver nicht möglich." }, "status.OAuthServerError": { - "message": " OAuth 2.0 Authentifizierungsserver meldet: ##replace.1##" + "message": " OAuth-2.0-Authentifizierungsserver meldet: ##replace.1##" }, "status.aborted": { "message": "Nicht synchronisiert" }, "status.apiError": { - "message": "API Implementierungsfehler" + "message": "API-Implementierungsfehler" }, "status.disabled": { "message": "Konto ist deaktiviert, Synchronisation ist ausgeschaltet." }, "status.foldererror": { - "message": "Bei mindestens einer Resource trat ein Synchronisationsfehler auf. Bitte prüfen sie das Ereignisprotokoll für weitere Details." + "message": "Bei mindestens einer Ressource trat ein Synchronisationsfehler auf. Bitte prüfen Sie das Ereignisprotokoll für weitere Details!" }, "status.modified": { "message": "Lokale Änderungen" @@ -282,10 +282,10 @@ "message": "Verbindung zum Server fehlgeschlagen (##replace.1##)." }, "status.no-folders-found-on-server": { - "message": "Auf dem Server wurden keine Resourcen gefunden." + "message": "Auf dem Server wurden keine Ressourcen gefunden." }, "status.notargets": { - "message": "Synchronisation abgebrochen da die Elemente zum Synchronisieren nicht erstellt werden konnten." + "message": "Synchronisation abgebrochen, da die Elemente zum Synchronisieren nicht erstellt werden konnten." }, "status.notsyncronized": { "message": "Konto muss synchronisiert werden." @@ -294,7 +294,7 @@ "message": "Warten auf Synchronisation" }, "status.security": { - "message": "Fehler beim Aufbau einer sicherern Verbindung. Benutzen Sie eventuell ein selbst signiertes Zertifikat oder ein andersartiges nicht vertrauenswürdiges Zertifikat welches nicht in Thunderbird importiert ist? (##replace.1##)" + "message": "Fehler beim Aufbau einer sicheren Verbindung. Benutzen Sie eventuell ein selbst signiertes oder anderweitig nicht vertrauenswürdiges Zertifikat, das nicht in Thunderbird importiert ist? (##replace.1##)" }, "status.skipped": { "message": "Nicht unterstützt" @@ -354,6 +354,12 @@ "message": "Synchronisiere alle TbSync Konten" }, "toolbar.tooltiptext": { - "message": "Gleiche alle TbSync Konten mit den Servern ab" + "message": "Gleiche alle TbSync-Konten mit den Servern ab" + }, + "password.ok": { + "message": "OK" + }, + "password.cancel": { + "message": "Abbrechen" } -} \ No newline at end of file +} diff -Nru tbsync-4.3/_locales/en-US/messages.json tbsync-4.7/_locales/en-US/messages.json --- tbsync-4.3/_locales/en-US/messages.json 2022-10-12 19:40:25.000000000 +0000 +++ tbsync-4.7/_locales/en-US/messages.json 2023-08-29 20:22:49.000000000 +0000 @@ -355,5 +355,11 @@ }, "toolbar.tooltiptext": { "message": "Synchronize latest changes" + }, + "password.ok": { + "message": "OK" + }, + "password.cancel": { + "message": "Cancel" } -} \ No newline at end of file +} diff -Nru tbsync-4.3/_locales/es/messages.json tbsync-4.7/_locales/es/messages.json --- tbsync-4.3/_locales/es/messages.json 2022-10-12 19:40:25.000000000 +0000 +++ tbsync-4.7/_locales/es/messages.json 2023-08-29 20:22:49.000000000 +0000 @@ -355,5 +355,11 @@ }, "toolbar.tooltiptext": { "message": "Sincronizar los últimos cambios" + }, + "password.ok": { + "message": "Aceptar" + }, + "password.cancel": { + "message": "Cancelar" } -} \ No newline at end of file +} diff -Nru tbsync-4.3/_locales/et/messages.json tbsync-4.7/_locales/et/messages.json --- tbsync-4.3/_locales/et/messages.json 2022-10-12 19:40:25.000000000 +0000 +++ tbsync-4.7/_locales/et/messages.json 2023-08-29 20:22:49.000000000 +0000 @@ -355,5 +355,11 @@ }, "toolbar.tooltiptext": { "message": "Synchronize latest changes" + }, + "password.ok": { + "message": "OK" + }, + "password.cancel": { + "message": "Tühista" } -} \ No newline at end of file +} diff -Nru tbsync-4.3/_locales/fr/messages.json tbsync-4.7/_locales/fr/messages.json --- tbsync-4.3/_locales/fr/messages.json 2022-10-12 19:40:25.000000000 +0000 +++ tbsync-4.7/_locales/fr/messages.json 2023-08-29 20:22:49.000000000 +0000 @@ -355,5 +355,11 @@ }, "toolbar.tooltiptext": { "message": "Synchroniser les dernières modifications" + }, + "password.ok": { + "message": "OK" + }, + "password.cancel": { + "message": "Annuler" } -} \ No newline at end of file +} diff -Nru tbsync-4.3/_locales/gl/messages.json tbsync-4.7/_locales/gl/messages.json --- tbsync-4.3/_locales/gl/messages.json 2022-10-12 19:40:25.000000000 +0000 +++ tbsync-4.7/_locales/gl/messages.json 2023-08-29 20:22:49.000000000 +0000 @@ -141,7 +141,7 @@ "message": "Ver rexistro de depuración" }, "manager.help.wiki": { - "message": "Abrir as páxinas wiki do proxecto TbSync nas que facilitan información adicional, guías e descricións detalladas da configuración." + "message": "Abre o wiki do proxecto TbSync no que se facilita información adicional, guías e descricións detalladas da configuración." }, "manager.installprovider.link": { "message": "Preme no seguinte enlace para abrir a páxina de información do provedor de sincronización que falta. Aí atoparás máis información sobre o provedor e terás a opción de instalalo:" @@ -355,5 +355,11 @@ }, "toolbar.tooltiptext": { "message": "Sincronizar os últimos cambios" + }, + "password.ok": { + "message": "Aceptar" + }, + "password.cancel": { + "message": "Cancelar" } -} \ No newline at end of file +} diff -Nru tbsync-4.3/_locales/hu/messages.json tbsync-4.7/_locales/hu/messages.json --- tbsync-4.3/_locales/hu/messages.json 2022-10-12 19:40:25.000000000 +0000 +++ tbsync-4.7/_locales/hu/messages.json 2023-08-29 20:22:49.000000000 +0000 @@ -355,5 +355,11 @@ }, "toolbar.tooltiptext": { "message": "A legújabb változtatások szinkronizálása" + }, + "password.ok": { + "message": "Rendben" + }, + "password.cancel": { + "message": "Mégse" } -} \ No newline at end of file +} diff -Nru tbsync-4.3/_locales/it/messages.json tbsync-4.7/_locales/it/messages.json --- tbsync-4.3/_locales/it/messages.json 2022-10-12 19:40:25.000000000 +0000 +++ tbsync-4.7/_locales/it/messages.json 2023-08-29 20:22:49.000000000 +0000 @@ -355,5 +355,11 @@ }, "toolbar.tooltiptext": { "message": "Sincronizza le ultime modifiche" + }, + "password.ok": { + "message": "OK" + }, + "password.cancel": { + "message": "Annulla" } -} \ No newline at end of file +} diff -Nru tbsync-4.3/_locales/ja/messages.json tbsync-4.7/_locales/ja/messages.json --- tbsync-4.3/_locales/ja/messages.json 2022-10-12 19:40:25.000000000 +0000 +++ tbsync-4.7/_locales/ja/messages.json 2023-08-29 20:22:49.000000000 +0000 @@ -355,5 +355,11 @@ }, "toolbar.tooltiptext": { "message": "最新の変更を同期" + }, + "password.ok": { + "message": "OK" + }, + "password.cancel": { + "message": "キャンセル" } -} \ No newline at end of file +} diff -Nru tbsync-4.3/_locales/ko/messages.json tbsync-4.7/_locales/ko/messages.json --- tbsync-4.3/_locales/ko/messages.json 2022-10-12 19:40:25.000000000 +0000 +++ tbsync-4.7/_locales/ko/messages.json 2023-08-29 20:22:49.000000000 +0000 @@ -355,5 +355,11 @@ }, "toolbar.tooltiptext": { "message": "Synchronize latest changes" + }, + "password.ok": { + "message": "확인" + }, + "password.cancel": { + "message": "취소" } -} \ No newline at end of file +} diff -Nru tbsync-4.3/_locales/pl/messages.json tbsync-4.7/_locales/pl/messages.json --- tbsync-4.3/_locales/pl/messages.json 2022-10-12 19:40:25.000000000 +0000 +++ tbsync-4.7/_locales/pl/messages.json 2023-08-29 20:22:49.000000000 +0000 @@ -355,5 +355,11 @@ }, "toolbar.tooltiptext": { "message": "Synchronizuj najnowsze zmiany" + }, + "password.ok": { + "message": "OK" + }, + "password.cancel": { + "message": "Anuluj" } -} \ No newline at end of file +} diff -Nru tbsync-4.3/_locales/pt_BR/messages.json tbsync-4.7/_locales/pt_BR/messages.json --- tbsync-4.3/_locales/pt_BR/messages.json 2022-10-12 19:40:25.000000000 +0000 +++ tbsync-4.7/_locales/pt_BR/messages.json 2023-08-29 20:22:49.000000000 +0000 @@ -355,5 +355,11 @@ }, "toolbar.tooltiptext": { "message": "Sincronizar as alterações mais recentes" + }, + "password.ok": { + "message": "OK" + }, + "password.cancel": { + "message": "Cancelar" } -} \ No newline at end of file +} diff -Nru tbsync-4.3/_locales/ro/messages.json tbsync-4.7/_locales/ro/messages.json --- tbsync-4.3/_locales/ro/messages.json 2022-10-12 19:40:25.000000000 +0000 +++ tbsync-4.7/_locales/ro/messages.json 2023-08-29 20:22:49.000000000 +0000 @@ -355,5 +355,11 @@ }, "toolbar.tooltiptext": { "message": "Synchronize latest changes" + }, + "password.ok": { + "message": "OK" + }, + "password.cancel": { + "message": "Anulare" } -} \ No newline at end of file +} diff -Nru tbsync-4.3/_locales/ru/messages.json tbsync-4.7/_locales/ru/messages.json --- tbsync-4.3/_locales/ru/messages.json 2022-10-12 19:40:25.000000000 +0000 +++ tbsync-4.7/_locales/ru/messages.json 2023-08-29 20:22:49.000000000 +0000 @@ -355,5 +355,11 @@ }, "toolbar.tooltiptext": { "message": "Синхронизировать последние изменения" + }, + "password.ok": { + "message": "ОК" + }, + "password.cancel": { + "message": "Отмена" } -} \ No newline at end of file +} diff -Nru tbsync-4.3/_locales/sv/messages.json tbsync-4.7/_locales/sv/messages.json --- tbsync-4.3/_locales/sv/messages.json 2022-10-12 19:40:25.000000000 +0000 +++ tbsync-4.7/_locales/sv/messages.json 2023-08-29 20:22:49.000000000 +0000 @@ -355,5 +355,11 @@ }, "toolbar.tooltiptext": { "message": "Synchronize latest changes" + }, + "password.ok": { + "message": "OK" + }, + "password.cancel": { + "message": "Avbryt" } -} \ No newline at end of file +} diff -Nru tbsync-4.3/content/api/BootstrapLoader/CHANGELOG.md tbsync-4.7/content/api/BootstrapLoader/CHANGELOG.md --- tbsync-4.3/content/api/BootstrapLoader/CHANGELOG.md 2022-10-12 19:40:25.000000000 +0000 +++ tbsync-4.7/content/api/BootstrapLoader/CHANGELOG.md 2023-08-29 20:22:49.000000000 +0000 @@ -1,3 +1,18 @@ +Version: 1.21 +------------- +- Explicitly set hasAddonManagerEventListeners flag to false on uninstall + +Version: 1.20 +------------- +- hard fork BootstrapLoader v1.19 implementation and continue to serve it for + Thunderbird 111 and older +- BootstrapLoader v1.20 has removed a lot of unnecessary code used for backward + compatibility + +Version: 1.19 +------------- +- fix race condition which could prevent the AOM tab to be monkey patched correctly + Version: 1.18 ------------- - be precise on which revision the wrench symbol should be displayed, instead of diff -Nru tbsync-4.3/content/api/BootstrapLoader/implementation.js tbsync-4.7/content/api/BootstrapLoader/implementation.js --- tbsync-4.3/content/api/BootstrapLoader/implementation.js 2022-10-12 19:40:25.000000000 +0000 +++ tbsync-4.7/content/api/BootstrapLoader/implementation.js 2023-08-29 20:22:49.000000000 +0000 @@ -2,7 +2,7 @@ * This file is provided by the addon-developer-support repository at * https://github.com/thundernest/addon-developer-support * - * Version: 1.18 + * Version: 1.21 * * Author: John Bieling (john@thunderbird.net) * @@ -17,70 +17,65 @@ var { AddonManager } = ChromeUtils.import("resource://gre/modules/AddonManager.jsm"); var { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm"); -var BootstrapLoader = class extends ExtensionCommon.ExtensionAPI { - getMessenger(context) { - let apis = [ - "storage", - "runtime", - "extension", - "i18n", - ]; - - function getStorage() { - let localstorage = null; - try { - localstorage = context.apiCan.findAPIPath("storage"); - localstorage.local.get = (...args) => - localstorage.local.callMethodInParentProcess("get", args); - localstorage.local.set = (...args) => - localstorage.local.callMethodInParentProcess("set", args); - localstorage.local.remove = (...args) => - localstorage.local.callMethodInParentProcess("remove", args); - localstorage.local.clear = (...args) => - localstorage.local.callMethodInParentProcess("clear", args); - } catch (e) { - console.info("Storage permission is missing"); - } - return localstorage; - } - - let messenger = {}; - for (let api of apis) { - switch (api) { - case "storage": - XPCOMUtils.defineLazyGetter(messenger, "storage", () => - getStorage() - ); - break; +function getThunderbirdVersion() { + let parts = Services.appinfo.version.split("."); + return { + major: parseInt(parts[0]), + minor: parseInt(parts[1]), + revision: parts.length > 2 ? parseInt(parts[2]) : 0, + } +} - default: - XPCOMUtils.defineLazyGetter(messenger, api, () => - context.apiCan.findAPIPath(api) - ); - } +function getMessenger(context) { + let apis = ["storage", "runtime", "extension", "i18n"]; + + function getStorage() { + let localstorage = null; + try { + localstorage = context.apiCan.findAPIPath("storage"); + localstorage.local.get = (...args) => + localstorage.local.callMethodInParentProcess("get", args); + localstorage.local.set = (...args) => + localstorage.local.callMethodInParentProcess("set", args); + localstorage.local.remove = (...args) => + localstorage.local.callMethodInParentProcess("remove", args); + localstorage.local.clear = (...args) => + localstorage.local.callMethodInParentProcess("clear", args); + } catch (e) { + console.info("Storage permission is missing"); } - return messenger; + return localstorage; } - getThunderbirdVersion() { - let parts = Services.appinfo.version.split("."); - return { - major: parseInt(parts[0]), - minor: parseInt(parts[1]), - revision: parts.length > 2 ? parseInt(parts[2]) : 0, + let messenger = {}; + for (let api of apis) { + switch (api) { + case "storage": + XPCOMUtils.defineLazyGetter(messenger, "storage", () => + getStorage() + ); + break; + + default: + XPCOMUtils.defineLazyGetter(messenger, api, () => + context.apiCan.findAPIPath(api) + ); } } - + return messenger; +} + +var BootstrapLoader_102 = class extends ExtensionCommon.ExtensionAPI { getCards(e) { // This gets triggered by real events but also manually by providing the outer window. // The event is attached to the outer browser, get the inner one. let doc; - + // 78,86, and 87+ need special handholding. *Yeah*. - if (this.getThunderbirdVersion().major < 86) { + if (getThunderbirdVersion().major < 86) { let ownerDoc = e.document || e.target.ownerDocument; doc = ownerDoc.getElementById("html-view-browser").contentDocument; - } else if (this.getThunderbirdVersion().major < 87) { + } else if (getThunderbirdVersion().major < 87) { let ownerDoc = e.document || e.target; doc = ownerDoc.getElementById("html-view-browser").contentDocument; } else { @@ -88,42 +83,42 @@ } return doc.querySelectorAll("addon-card"); } - + // Add pref entry to 68 add68PrefsEntry(event) { let id = this.menu_addonPrefs_id + "_" + this.uniqueRandomID; // Get the best size of the icon (16px or bigger) - let iconSizes = this.extension.manifest.icons + let iconSizes = this.extension.manifest.icons ? Object.keys(this.extension.manifest.icons) : []; - iconSizes.sort((a,b)=>a-b); + iconSizes.sort((a, b) => a - b); let bestSize = iconSizes.filter(e => parseInt(e) >= 16).shift(); let icon = bestSize ? this.extension.manifest.icons[bestSize] : ""; let name = this.extension.manifest.name; let entry = icon ? event.target.ownerGlobal.MozXULElement.parseXULToFragment( - ``) - : event.target.ownerGlobal.MozXULElement.parseXULToFragment( - ``); - + ``) + : event.target.ownerGlobal.MozXULElement.parseXULToFragment( + ``); + event.target.appendChild(entry); let noPrefsElem = event.target.querySelector('[disabled="true"]'); // using collapse could be undone by core, so we use display none // noPrefsElem.setAttribute("collapsed", "true"); noPrefsElem.style.display = "none"; event.target.ownerGlobal.document.getElementById(id).addEventListener("command", this); - } + } // Event handler for the addon manager, to update the state of the options button. - handleEvent(e) { + handleEvent(e) { switch (e.type) { // 68 add-on options menu showing case "popupshowing": { this.add68PrefsEntry(e); } - break; + break; // 78/88 add-on options menu/button click case "click": { @@ -131,31 +126,31 @@ e.stopPropagation(); let BL = {} BL.extension = this.extension; - BL.messenger = this.getMessenger(this.context); + BL.messenger = getMessenger(this.context); let w = Services.wm.getMostRecentWindow("mail:3pane"); - w.openDialog(this.pathToOptionsPage, "AddonOptions", "chrome,resizable,centerscreen", BL); + w.openDialog(this.pathToOptionsPage, "AddonOptions", "chrome,resizable,centerscreen", BL); } - break; - + break; + // 68 add-on options menu command case "command": { let BL = {} BL.extension = this.extension; - BL.messenger = this.getMessenger(this.context); + BL.messenger = getMessenger(this.context); e.target.ownerGlobal.openDialog(this.pathToOptionsPage, "AddonOptions", "chrome,resizable,centerscreen", BL); } - break; - + break; + // update, ViewChanged and manual call for add-on manager options overlay default: { let cards = this.getCards(e); for (let card of cards) { // Setup either the options entry in the menu or the button if (card.addon.id == this.extension.id) { - let optionsMenu = - (this.getThunderbirdVersion().major > 78 && this.getThunderbirdVersion().major < 88) || - (this.getThunderbirdVersion().major == 78 && this.getThunderbirdVersion().minor < 10) || - (this.getThunderbirdVersion().major == 78 && this.getThunderbirdVersion().minor == 10 && this.getThunderbirdVersion().revision < 2); + let optionsMenu = + (getThunderbirdVersion().major > 78 && getThunderbirdVersion().major < 88) || + (getThunderbirdVersion().major == 78 && getThunderbirdVersion().minor < 10) || + (getThunderbirdVersion().major == 78 && getThunderbirdVersion().minor == 10 && getThunderbirdVersion().revision < 2); if (optionsMenu) { // Options menu in 78.0-78.10 and 79-87 let addonOptionsLegacyEntry = card.querySelector(".extension-options-legacy"); @@ -204,10 +199,10 @@ } } } - } - } - -// Some tab/add-on-manager related functions + } + } + + // Some tab/add-on-manager related functions getTabMail(window) { return window.document.getElementById("tabmail"); } @@ -215,7 +210,7 @@ // returns the outer browser, not the nested browser of the add-on manager // events must be attached to the outer browser getAddonManagerFromTab(tab) { - if (tab.browser) { + if (tab.browser && tab.mode.name == "contentTab") { let win = tab.browser.contentWindow; if (win && win.location.href == "about:addons") { return win; @@ -226,9 +221,28 @@ getAddonManagerFromWindow(window) { let tabMail = this.getTabMail(window); for (let tab of tabMail.tabInfo) { - let win = this.getAddonManagerFromTab(tab) - if (win) { - return win; + let managerWindow = this.getAddonManagerFromTab(tab); + if (managerWindow) { + return managerWindow; + } + } + } + + async getAddonManagerFromWindowWaitForLoad(window) { + let { setTimeout } = Services.wm.getMostRecentWindow("mail:3pane"); + + let tabMail = this.getTabMail(window); + for (let tab of tabMail.tabInfo) { + if (tab.browser && tab.mode.name == "contentTab") { + // Instead of registering a load observer, wait until its loaded. Not nice, + // but gets aroud a lot of edge cases. + while (!tab.pageLoaded) { + await new Promise(r => setTimeout(r, 150)); + } + let managerWindow = this.getAddonManagerFromTab(tab); + if (managerWindow) { + return managerWindow; + } } } } @@ -237,15 +251,16 @@ if (!managerWindow) { return; } - if (managerWindow - && managerWindow[this.uniqueRandomID] - && managerWindow[this.uniqueRandomID].hasAddonManagerEventListeners + if ( + managerWindow && + managerWindow[this.uniqueRandomID] && + managerWindow[this.uniqueRandomID].hasAddonManagerEventListeners ) { return; } managerWindow.document.addEventListener("ViewChanged", this); managerWindow.document.addEventListener("update", this); - managerWindow.document.addEventListener("view-loaded", this); + managerWindow.document.addEventListener("view-loaded", this); managerWindow[this.uniqueRandomID] = {}; managerWindow[this.uniqueRandomID].hasAddonManagerEventListeners = true; if (forceLoad) { @@ -262,13 +277,13 @@ this.pathToOptionsPage = null; this.chromeHandle = null; this.chromeData = null; - this.resourceData = null; + this.resourceData = null; this.bootstrappedObj = {}; // make the extension object and the messenger object available inside // the bootstrapped scope this.bootstrappedObj.extension = context.extension; - this.bootstrappedObj.messenger = this.getMessenger(this.context); + this.bootstrappedObj.messenger = getMessenger(this.context); this.BOOTSTRAP_REASONS = { APP_STARTUP: 1, @@ -283,49 +298,413 @@ const aomStartup = Cc["@mozilla.org/addons/addon-manager-startup;1"].getService(Ci.amIAddonManagerStartup); const resProto = Cc["@mozilla.org/network/protocol;1?name=resource"].getService(Ci.nsISubstitutingProtocolHandler); - + let self = this; // TabMonitor to detect opening of tabs, to setup the options button in the add-on manager. this.tabMonitor = { - onTabTitleChanged(aTab) {}, - onTabClosing(aTab) {}, - onTabPersist(aTab) {}, - onTabRestored(aTab) {}, - onTabSwitched(aNewTab, aOldTab) { - //self.setupAddonManager(self.getAddonManagerFromTab(aNewTab)); + onTabTitleChanged(tab) { }, + onTabClosing(tab) { }, + onTabPersist(tab) { }, + onTabRestored(tab) { }, + onTabSwitched(aNewTab, aOldTab) { }, + async onTabOpened(tab) { + if (tab.browser && tab.mode.name == "contentTab") { + let { setTimeout } = Services.wm.getMostRecentWindow("mail:3pane"); + // Instead of registering a load observer, wait until its loaded. Not nice, + // but gets aroud a lot of edge cases. + while (!tab.pageLoaded) { + await new Promise(r => setTimeout(r, 150)); + } + self.setupAddonManager(self.getAddonManagerFromTab(tab)); + } }, - async onTabOpened(aTab) { - if (aTab.browser) { - if (!aTab.pageLoaded) { - // await a location change if browser is not loaded yet - await new Promise(resolve => { - let reporterListener = { - QueryInterface: ChromeUtils.generateQI([ - "nsIWebProgressListener", - "nsISupportsWeakReference", - ]), - onStateChange() {}, - onProgressChange() {}, - onLocationChange( - /* in nsIWebProgress*/ aWebProgress, - /* in nsIRequest*/ aRequest, - /* in nsIURI*/ aLocation - ) { - aTab.browser.removeProgressListener(reporterListener); - resolve(); - }, - onStatusChange() {}, - onSecurityChange() {}, - onContentBlockingEvent() {} - } - aTab.browser.addProgressListener(reporterListener); + }; + + return { + BootstrapLoader: { + + registerOptionsPage(optionsUrl) { + self.pathToOptionsPage = optionsUrl.startsWith("chrome://") + ? optionsUrl + : context.extension.rootURI.resolve(optionsUrl); + }, + + openOptionsDialog(windowId) { + let window = context.extension.windowManager.get(windowId, context).window + let BL = {} + BL.extension = self.extension; + BL.messenger = getMessenger(self.context); + window.openDialog(self.pathToOptionsPage, "AddonOptions", "chrome,resizable,centerscreen", BL); + }, + + registerChromeUrl(data) { + let chromeData = []; + let resourceData = []; + for (let entry of data) { + if (entry[0] == "resource") resourceData.push(entry); + else chromeData.push(entry) + } + + if (chromeData.length > 0) { + const manifestURI = Services.io.newURI( + "manifest.json", + null, + context.extension.rootURI + ); + self.chromeHandle = aomStartup.registerChrome(manifestURI, chromeData); + } + + for (let res of resourceData) { + // [ "resource", "shortname" , "path" ] + let uri = Services.io.newURI( + res[2], + null, + context.extension.rootURI + ); + resProto.setSubstitutionWithFlags( + res[1], + uri, + resProto.ALLOW_CONTENT_ACCESS + ); + } + + self.chromeData = chromeData; + self.resourceData = resourceData; + }, + + registerBootstrapScript: async function (aPath) { + self.pathToBootstrapScript = aPath.startsWith("chrome://") + ? aPath + : context.extension.rootURI.resolve(aPath); + + // Get the addon object belonging to this extension. + let addon = await AddonManager.getAddonByID(context.extension.id); + //make the addon globally available in the bootstrapped scope + self.bootstrappedObj.addon = addon; + + // add BOOTSTRAP_REASONS to scope + for (let reason of Object.keys(self.BOOTSTRAP_REASONS)) { + self.bootstrappedObj[reason] = self.BOOTSTRAP_REASONS[reason]; + } + + // Load registered bootstrap scripts and execute its startup() function. + try { + if (self.pathToBootstrapScript) Services.scriptloader.loadSubScript(self.pathToBootstrapScript, self.bootstrappedObj, "UTF-8"); + if (self.bootstrappedObj.startup) self.bootstrappedObj.startup.call(self.bootstrappedObj, self.extension.addonData, self.BOOTSTRAP_REASONS[self.extension.startupReason]); + } catch (e) { + Components.utils.reportError(e) + } + + // Register window listener for main TB window + if (self.pathToOptionsPage) { + ExtensionSupport.registerWindowListener("injectListener_" + self.uniqueRandomID, { + chromeURLs: [ + "chrome://messenger/content/messenger.xul", + "chrome://messenger/content/messenger.xhtml", + ], + async onLoadWindow(window) { + if (getThunderbirdVersion().major < 78) { + let element_addonPrefs = window.document.getElementById(self.menu_addonPrefs_id); + element_addonPrefs.addEventListener("popupshowing", self); + } else { + // Add a tabmonitor, to be able to setup the options button/menu in the add-on manager. + self.getTabMail(window).registerTabMonitor(self.tabMonitor); + window[self.uniqueRandomID] = {}; + window[self.uniqueRandomID].hasTabMonitor = true; + // Setup the options button/menu in the add-on manager, if it is already open. + let managerWindow = await self.getAddonManagerFromWindowWaitForLoad(window); + self.setupAddonManager(managerWindow, true); + } + }, + + onUnloadWindow(window) { + } }); } - // Setup the ViewChange event listener in the outer browser of the add-on, - // but do not actually add the button/menu, as the inner browser is not yet ready, - // let the ViewChange event do it - self.setupAddonManager(self.getAddonManagerFromTab(aTab)); + } + } + }; + } + + onShutdown(isAppShutdown) { + if (isAppShutdown) { + return; // the application gets unloaded anyway + } + + //remove our entry in the add-on options menu + if (this.pathToOptionsPage) { + for (let window of Services.wm.getEnumerator("mail:3pane")) { + if (getThunderbirdVersion().major < 78) { + let element_addonPrefs = window.document.getElementById(this.menu_addonPrefs_id); + element_addonPrefs.removeEventListener("popupshowing", this); + // Remove our entry. + let entry = window.document.getElementById(this.menu_addonPrefs_id + "_" + this.uniqueRandomID); + if (entry) entry.remove(); + // Do we have to unhide the noPrefsElement? + if (element_addonPrefs.children.length == 1) { + let noPrefsElem = element_addonPrefs.querySelector('[disabled="true"]'); + noPrefsElem.style.display = "inline"; + } + } else { + // Remove event listener for addon manager view changes + let managerWindow = this.getAddonManagerFromWindow(window); + if ( + managerWindow && + managerWindow[this.uniqueRandomID] && + managerWindow[this.uniqueRandomID].hasAddonManagerEventListeners + ) { + managerWindow.document.removeEventListener("ViewChanged", this); + managerWindow.document.removeEventListener("update", this); + managerWindow.document.removeEventListener("view-loaded", this); + managerWindow[this.uniqueRandomID].hasAddonManagerEventListeners = false; + + let cards = this.getCards(managerWindow); + if (getThunderbirdVersion().major < 88) { + // Remove options menu in 78-87 + for (let card of cards) { + let addonOptionsLegacyEntry = card.querySelector(".extension-options-legacy"); + if (addonOptionsLegacyEntry) addonOptionsLegacyEntry.remove(); + } + } else { + // Remove options button in 88 + for (let card of cards) { + if (card.addon.id == this.extension.id) { + let addonOptionsButton = card.querySelector(".extension-options-button2"); + if (addonOptionsButton) addonOptionsButton.remove(); + break; + } + } + } + } + + // Remove tabmonitor + if (window[this.uniqueRandomID].hasTabMonitor) { + this.getTabMail(window).unregisterTabMonitor(this.tabMonitor); + window[this.uniqueRandomID].hasTabMonitor = false; + } + + } + } + // Stop listening for new windows. + ExtensionSupport.unregisterWindowListener("injectListener_" + this.uniqueRandomID); + } + + // Execute registered shutdown() + try { + if (this.bootstrappedObj.shutdown) { + this.bootstrappedObj.shutdown( + this.extension.addonData, + isAppShutdown + ? this.BOOTSTRAP_REASONS.APP_SHUTDOWN + : this.BOOTSTRAP_REASONS.ADDON_DISABLE); + } + } catch (e) { + Components.utils.reportError(e) + } + + if (this.resourceData) { + const resProto = Cc["@mozilla.org/network/protocol;1?name=resource"].getService(Ci.nsISubstitutingProtocolHandler); + for (let res of this.resourceData) { + // [ "resource", "shortname" , "path" ] + resProto.setSubstitution( + res[1], + null, + ); + } + } + + if (this.chromeHandle) { + this.chromeHandle.destruct(); + this.chromeHandle = null; + } + // Flush all caches + Services.obs.notifyObservers(null, "startupcache-invalidate"); + console.log("BootstrapLoader for " + this.extension.id + " unloaded!"); + } +}; + +// Removed all extra code for backward compatibility for better maintainability. +var BootstrapLoader_115 = class extends ExtensionCommon.ExtensionAPI { + getCards(e) { + // This gets triggered by real events but also manually by providing the outer window. + // The event is attached to the outer browser, get the inner one. + let doc = e.document || e.target; + return doc.querySelectorAll("addon-card"); + } + + // Event handler for the addon manager, to update the state of the options button. + handleEvent(e) { + switch (e.type) { + case "click": { + e.preventDefault(); + e.stopPropagation(); + let BL = {} + BL.extension = this.extension; + BL.messenger = getMessenger(this.context); + let w = Services.wm.getMostRecentWindow("mail:3pane"); + w.openDialog( + this.pathToOptionsPage, + "AddonOptions", + "chrome,resizable,centerscreen", + BL + ); + } + break; + + + // update, ViewChanged and manual call for add-on manager options overlay + default: { + let cards = this.getCards(e); + for (let card of cards) { + // Setup either the options entry in the menu or the button + if (card.addon.id == this.extension.id) { + // Add-on button + let addonOptionsButton = card.querySelector( + ".windowlistener-options-button" + ); + if (card.addon.isActive && !addonOptionsButton) { + let origAddonOptionsButton = card.querySelector(".extension-options-button") + origAddonOptionsButton.setAttribute("hidden", "true"); + + addonOptionsButton = card.ownerDocument.createElement("button"); + addonOptionsButton.classList.add("windowlistener-options-button"); + addonOptionsButton.classList.add("extension-options-button"); + card.optionsButton.parentNode.insertBefore( + addonOptionsButton, + card.optionsButton + ); + card + .querySelector(".windowlistener-options-button") + .addEventListener("click", this); + } else if (!card.addon.isActive && addonOptionsButton) { + addonOptionsButton.remove(); + } + } + } + } + } + } + + // Some tab/add-on-manager related functions + getTabMail(window) { + return window.document.getElementById("tabmail"); + } + + // returns the outer browser, not the nested browser of the add-on manager + // events must be attached to the outer browser + getAddonManagerFromTab(tab) { + if (tab.browser && tab.mode.name == "contentTab") { + let win = tab.browser.contentWindow; + if (win && win.location.href == "about:addons") { + return win; + } + } + } + + getAddonManagerFromWindow(window) { + let tabMail = this.getTabMail(window); + for (let tab of tabMail.tabInfo) { + let managerWindow = this.getAddonManagerFromTab(tab); + if (managerWindow) { + return managerWindow; + } + } + } + + async getAddonManagerFromWindowWaitForLoad(window) { + let { setTimeout } = Services.wm.getMostRecentWindow("mail:3pane"); + + let tabMail = this.getTabMail(window); + for (let tab of tabMail.tabInfo) { + if (tab.browser && tab.mode.name == "contentTab") { + // Instead of registering a load observer, wait until its loaded. Not nice, + // but gets aroud a lot of edge cases. + while (!tab.pageLoaded) { + await new Promise(r => setTimeout(r, 150)); + } + let managerWindow = this.getAddonManagerFromTab(tab); + if (managerWindow) { + return managerWindow; + } + } + } + } + + setupAddonManager(managerWindow, forceLoad = false) { + if (!managerWindow) { + return; + } + if (!this.pathToOptionsPage) { + return; + } + if ( + managerWindow && + managerWindow[this.uniqueRandomID] && + managerWindow[this.uniqueRandomID].hasAddonManagerEventListeners + ) { + return; + } + + managerWindow.document.addEventListener("ViewChanged", this); + managerWindow.document.addEventListener("update", this); + managerWindow.document.addEventListener("view-loaded", this); + managerWindow[this.uniqueRandomID] = {}; + managerWindow[this.uniqueRandomID].hasAddonManagerEventListeners = true; + if (forceLoad) { + this.handleEvent(managerWindow); + } + } + + getAPI(context) { + this.uniqueRandomID = "AddOnNS" + context.extension.instanceId; + this.menu_addonPrefs_id = "addonPrefs"; + + + this.pathToBootstrapScript = null; + this.pathToOptionsPage = null; + this.chromeHandle = null; + this.chromeData = null; + this.resourceData = null; + this.bootstrappedObj = {}; + + // make the extension object and the messenger object available inside + // the bootstrapped scope + this.bootstrappedObj.extension = context.extension; + this.bootstrappedObj.messenger = getMessenger(this.context); + + this.BOOTSTRAP_REASONS = { + APP_STARTUP: 1, + APP_SHUTDOWN: 2, + ADDON_ENABLE: 3, + ADDON_DISABLE: 4, + ADDON_INSTALL: 5, + ADDON_UNINSTALL: 6, // not supported + ADDON_UPGRADE: 7, + ADDON_DOWNGRADE: 8, + }; + + const aomStartup = Cc["@mozilla.org/addons/addon-manager-startup;1"].getService(Ci.amIAddonManagerStartup); + const resProto = Cc["@mozilla.org/network/protocol;1?name=resource"].getService(Ci.nsISubstitutingProtocolHandler); + + let self = this; + + // TabMonitor to detect opening of tabs, to setup the options button in the add-on manager. + this.tabMonitor = { + onTabTitleChanged(tab) { }, + onTabClosing(tab) { }, + onTabPersist(tab) { }, + onTabRestored(tab) { }, + onTabSwitched(aNewTab, aOldTab) { }, + async onTabOpened(tab) { + if (tab.browser && tab.mode.name == "contentTab") { + let { setTimeout } = Services.wm.getMostRecentWindow("mail:3pane"); + // Instead of registering a load observer, wait until its loaded. Not nice, + // but gets aroud a lot of edge cases. + while (!tab.pageLoaded) { + await new Promise(r => setTimeout(r, 150)); + } + self.setupAddonManager(self.getAddonManagerFromTab(tab)); } }, }; @@ -343,8 +722,8 @@ let window = context.extension.windowManager.get(windowId, context).window let BL = {} BL.extension = self.extension; - BL.messenger = self.getMessenger(self.context); - window.openDialog(self.pathToOptionsPage, "AddonOptions", "chrome,resizable,centerscreen", BL); + BL.messenger = getMessenger(self.context); + window.openDialog(self.pathToOptionsPage, "AddonOptions", "chrome,resizable,centerscreen", BL); }, registerChromeUrl(data) { @@ -382,7 +761,7 @@ self.resourceData = resourceData; }, - registerBootstrapScript: async function(aPath) { + registerBootstrapScript: async function (aPath) { self.pathToBootstrapScript = aPath.startsWith("chrome://") ? aPath : context.extension.rootURI.resolve(aPath); @@ -404,32 +783,30 @@ } catch (e) { Components.utils.reportError(e) } - + // Register window listener for main TB window if (self.pathToOptionsPage) { ExtensionSupport.registerWindowListener("injectListener_" + self.uniqueRandomID, { chromeURLs: [ "chrome://messenger/content/messenger.xul", - "chrome://messenger/content/messenger.xhtml", + "chrome://messenger/content/messenger.xhtml", ], async onLoadWindow(window) { - if (self.getThunderbirdVersion().major < 78) { + if (getThunderbirdVersion().major < 78) { let element_addonPrefs = window.document.getElementById(self.menu_addonPrefs_id); element_addonPrefs.addEventListener("popupshowing", self); } else { - // Setup the options button/menu in the add-on manager, if it is already open. - self.setupAddonManager( - self.getAddonManagerFromWindow(window), - true - ); // Add a tabmonitor, to be able to setup the options button/menu in the add-on manager. self.getTabMail(window).registerTabMonitor(self.tabMonitor); window[self.uniqueRandomID] = {}; window[self.uniqueRandomID].hasTabMonitor = true; + // Setup the options button/menu in the add-on manager, if it is already open. + let managerWindow = await self.getAddonManagerFromWindowWaitForLoad(window); + self.setupAddonManager(managerWindow, true); } }, - onUnloadWindow(window) { + onUnloadWindow(window) { } }); } @@ -442,11 +819,11 @@ if (isAppShutdown) { return; // the application gets unloaded anyway } - + //remove our entry in the add-on options menu if (this.pathToOptionsPage) { for (let window of Services.wm.getEnumerator("mail:3pane")) { - if (this.getThunderbirdVersion().major < 78) { + if (getThunderbirdVersion().major < 78) { let element_addonPrefs = window.document.getElementById(this.menu_addonPrefs_id); element_addonPrefs.removeEventListener("popupshowing", this); // Remove our entry. @@ -454,19 +831,24 @@ if (entry) entry.remove(); // Do we have to unhide the noPrefsElement? if (element_addonPrefs.children.length == 1) { - let noPrefsElem = element_addonPrefs.querySelector('[disabled="true"]'); - noPrefsElem.style.display = "inline"; - } + let noPrefsElem = element_addonPrefs.querySelector('[disabled="true"]'); + noPrefsElem.style.display = "inline"; + } } else { // Remove event listener for addon manager view changes let managerWindow = this.getAddonManagerFromWindow(window); - if (managerWindow && managerWindow[this.uniqueRandomID] && managerWindow[this.uniqueRandomID].hasAddonManagerEventListeners) { + if ( + managerWindow && + managerWindow[this.uniqueRandomID] && + managerWindow[this.uniqueRandomID].hasAddonManagerEventListeners + ) { managerWindow.document.removeEventListener("ViewChanged", this); managerWindow.document.removeEventListener("update", this); managerWindow.document.removeEventListener("view-loaded", this); - + managerWindow[this.uniqueRandomID].hasAddonManagerEventListeners = false; + let cards = this.getCards(managerWindow); - if (this.getThunderbirdVersion().major < 88) { + if (getThunderbirdVersion().major < 88) { // Remove options menu in 78-87 for (let card of cards) { let addonOptionsLegacyEntry = card.querySelector(".extension-options-legacy"); @@ -483,13 +865,13 @@ } } } - + // Remove tabmonitor if (window[this.uniqueRandomID].hasTabMonitor) { this.getTabMail(window).unregisterTabMonitor(this.tabMonitor); window[this.uniqueRandomID].hasTabMonitor = false; } - + } } // Stop listening for new windows. @@ -529,3 +911,7 @@ console.log("BootstrapLoader for " + this.extension.id + " unloaded!"); } }; + +var BootstrapLoader = getThunderbirdVersion().major < 111 + ? BootstrapLoader_102 + : BootstrapLoader_115; diff -Nru tbsync-4.3/content/api/BootstrapLoader/schema.json tbsync-4.7/content/api/BootstrapLoader/schema.json --- tbsync-4.3/content/api/BootstrapLoader/schema.json 2022-10-12 19:40:25.000000000 +0000 +++ tbsync-4.7/content/api/BootstrapLoader/schema.json 2023-08-29 20:22:49.000000000 +0000 @@ -35,7 +35,7 @@ "type": "array", "items": { "type": "array", - "items" : { + "items": { "type": "string" } }, @@ -58,4 +58,4 @@ } ] } -] +] \ No newline at end of file diff -Nru tbsync-4.3/content/manager/accounts.js tbsync-4.7/content/manager/accounts.js --- tbsync-4.3/content/manager/accounts.js 2022-10-12 19:40:25.000000000 +0000 +++ tbsync-4.7/content/manager/accounts.js 2023-08-29 20:22:49.000000000 +0000 @@ -370,9 +370,9 @@ //add icon (use "install provider" icon, if provider not installed) let itemType = document.createXULElement("image"); - itemType.setAttribute("width", "16"); - itemType.setAttribute("height", "16"); - itemType.setAttribute("style", "margin: 0px 0px 0px 5px;"); + //itemType.setAttribute("width", "16"); + //itemType.setAttribute("height", "16"); + itemType.setAttribute("style", "margin: 0px 0px 0px 5px; width:16px; height:16px"); newListItem.appendChild(itemType); //add account name @@ -382,9 +382,9 @@ //add account status let itemStatus = document.createXULElement("image"); - itemStatus.setAttribute("width", "16"); - itemStatus.setAttribute("height", "16"); - itemStatus.setAttribute("style", "margin: 0px 5px;"); + //itemStatus.setAttribute("width", "16"); + //itemStatus.setAttribute("height", "16"); + itemStatus.setAttribute("style", "margin: 0px 5px; width:16px; height:16px"); newListItem.appendChild(itemStatus); accountsList.appendChild(newListItem); diff -Nru tbsync-4.3/content/manager/accounts.xhtml tbsync-4.7/content/manager/accounts.xhtml --- tbsync-4.3/content/manager/accounts.xhtml 2022-10-12 19:40:25.000000000 +0000 +++ tbsync-4.7/content/manager/accounts.xhtml 2023-08-29 20:22:49.000000000 +0000 @@ -45,9 +45,9 @@ diff -Nru tbsync-4.3/content/manager/editAccount.js tbsync-4.7/content/manager/editAccount.js --- tbsync-4.3/content/manager/editAccount.js 2022-10-12 19:40:25.000000000 +0000 +++ tbsync-4.7/content/manager/editAccount.js 2023-08-29 20:22:49.000000000 +0000 @@ -9,7 +9,6 @@ "use strict"; var { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm"); -var { OS } =ChromeUtils.import("resource://gre/modules/osfile.jsm"); var { TbSync } = ChromeUtils.import("chrome://tbsync/content/tbsync.jsm"); var tbSyncAccountSettings = { @@ -104,7 +103,7 @@ document.getElementById('tbsync.accountsettings.frame').hidden = false; tbSyncAccountSettings.updateFolderList(); - if (OS.Constants.Sys.Name == "Darwin") { //we might need to find a way to detect MacOS like styling, other themes move the header bar into the tabpanel as well + if (Services.appinfo.OS == "Darwin") { //we might need to find a way to detect MacOS like styling, other themes move the header bar into the tabpanel as well document.getElementById('manager.tabpanels').style["padding-top"] = "3ex"; } }, diff -Nru tbsync-4.3/content/manager/editAccount.xhtml tbsync-4.7/content/manager/editAccount.xhtml --- tbsync-4.3/content/manager/editAccount.xhtml 2022-10-12 19:40:25.000000000 +0000 +++ tbsync-4.7/content/manager/editAccount.xhtml 2023-08-29 20:22:49.000000000 +0000 @@ -39,11 +39,11 @@