tbb-commits
Threads by month
- ----- 2025 -----
- 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 2024
- 1 participants
- 128 discussions

[Git][tpo/applications/tor-browser-build] Pushed new tag mb-13.5a4-build1
by richard (@richard) 29 Jan '24
by richard (@richard) 29 Jan '24
29 Jan '24
richard pushed new tag mb-13.5a4-build1 at The Tor Project / Applications / tor-browser-build
--
View it on GitLab: https://gitlab.torproject.org/tpo/applications/tor-browser-build/-/tree/mb-…
You're receiving this email because of your account on gitlab.torproject.org.
1
0

[Git][tpo/applications/mullvad-browser] Pushed new tag mullvad-browser-115.7.0esr-13.5-1-build2
by richard (@richard) 29 Jan '24
by richard (@richard) 29 Jan '24
29 Jan '24
richard pushed new tag mullvad-browser-115.7.0esr-13.5-1-build2 at The Tor Project / Applications / Mullvad Browser
--
View it on GitLab: https://gitlab.torproject.org/tpo/applications/mullvad-browser/-/tree/mullv…
You're receiving this email because of your account on gitlab.torproject.org.
1
0

[Git][tpo/applications/tor-browser-build][main] Bug 41051, 41052: Tor, Mullvad Browser 13.5a4 Release Prep
by richard (@richard) 29 Jan '24
by richard (@richard) 29 Jan '24
29 Jan '24
richard pushed to branch main at The Tor Project / Applications / tor-browser-build
Commits:
ecb3b0bf by Richard Pospesel at 2024-01-29T17:40:35+00:00
Bug 41051,41052: Tor,Mullvad Browser 13.5a4 Release Prep
- - - - -
12 changed files:
- projects/browser/Bundle-Data/Docs-MB/ChangeLog.txt
- projects/browser/Bundle-Data/Docs-TBB/ChangeLog.txt
- projects/browser/allowed_addons.json
- projects/browser/config
- projects/firefox-android/config
- projects/firefox/config
- projects/geckoview/…
[View More]config
- projects/go/config
- projects/manual/config
- projects/translation/config
- projects/zlib/config
- rbm.conf
Changes:
=====================================
projects/browser/Bundle-Data/Docs-MB/ChangeLog.txt
=====================================
@@ -1,3 +1,47 @@
+Mullvad Browser 13.5a4 - January 29 2024
+ * All Platforms
+ * Updated Firefox to 115.7.0esr
+ * Updated uBlock Origin to 1.55.0
+ * Bug 261: Rebase Mullvad Browser Alpha onto Firefox 115.7.0esr [mullvad-browser]
+ * Bug 41917: Make the appearance of letterboxing look more intentional [tor-browser]
+ * Bug 42374: spoof english leaks via numberingSystem: numbers (non-latn) or decimal separator (latn) [tor-browser]
+ * Build System
+ * All Platforms
+ * Bug 42337: Enable GeckoDriver for all desktop platforms [tor-browser]
+ * Bug 41037: Set time on signing machine before starting signing [tor-browser-build]
+ * Bug 41045: Dump more information about build times on Firefox [tor-browser-build]
+ * Bug 41056: Make it possible to use templates in var/torbrowser_incremental_from [tor-browser-build]
+ * Bug 41057: make fetch is not fetching mullvad repo [tor-browser-build]
+ * Bug 41059: Update keyring/torbrowser.gpg with updated key [tor-browser-build]
+ * Windows
+ * Bug 40606: Use Clang to compile NSIS [tor-browser-build]
+ * Bug 40900: Update NSIS to 3.09 [tor-browser-build]
+ * Bug 41065: Do a cleanup of the NSIS script [tor-browser-build]
+ * Linux
+ * Bug 41046: Use the final path for Linux debug symbols [tor-browser-build]
+
+Mullvad Browser 13.0.9 - January 23 2024
+ * All Platforms
+ * Updated Firefox to 115.7.0esr
+ * Updated uBlock Origin to 1.55.0
+ * Bug 249: BrowserHost has null mRoot when applying initial window size in debug [mullvad-browser]
+ * Bug 260: Rebase Mullvad Browser Stable onto Firefox 115.7.0esr [mullvad-browser]
+ * Bug 42189: Assertion failure: the value of mPrivateBrowsingId in the loadContext and in the loadInfo are not the same! [tor-browser]
+ * Bug 41044: Add tbb_version.json-like file for Mullvad Browser [tor-browser-build]
+ * Linux
+ * Bug 41050: Improve the disk leak sanitization on start-$browser [tor-browser-build]
+ * Build System
+ * All Platforms
+ * Bug 41042: Add options to include updates in the changelog scripts [tor-browser-build]
+ * Bug 41043: Create script to push build requests to Mullvad build servers [tor-browser-build]
+ * Bug 41056: Make it possible to use templates in var/torbrowser_incremental_from [tor-browser-build]
+ * Bug 41059: Update keyring/torbrowser.gpg with updated key [tor-browser-build]
+ * Bug 40067: Use --no-verbose wget option when not running in a terminal [rbm]
+ * Windows + macOS
+ * Bug 41016: Switch from bullseye to bookworm for desktop platforms [tor-browser-build]
+ * Windows
+ * Bug 41015: Enable std::filesystem on libc++ on Windows [tor-browser-build]
+
Mullvad Browser 13.5a3 - December 20 2023
* All Platforms
* Updated Firefox to 115.6.0esr
=====================================
projects/browser/Bundle-Data/Docs-TBB/ChangeLog.txt
=====================================
@@ -1,3 +1,77 @@
+Tor Browser 13.5a4 - January 29 2024
+ * All Platforms
+ * Updated zlib to 1.3.1
+ * Updated Snowflake to 2.8.1
+ * Bug 42343: Consume pt_config.json in the browser [tor-browser]
+ * Bug 42348: TorSettings.defaultSettings() removed but still referenced by Moat.sys.mjs [tor-browser]
+ * Bug 42354: Refactor exclusions in ShouldSanitizePreference() to the pref list. [tor-browser]
+ * Bug 42358: Separate the domain fronted requests from Moat [tor-browser]
+ * Bug 42359: Handle firewall and proxy in TorSettings.setSettings [tor-browser]
+ * Bug 42363: Tab thumbnails enhancements [tor-browser]
+ * Bug 42366: Rebase Tor Browser Alpha onto Firefox 115.7.0esr [tor-browser]
+ * Bug 42369: Revert YEC 2023 changes [tor-browser]
+ * Bug 42374: spoof english leaks via numberingSystem: numbers (non-latn) or decimal separator (latn) [tor-browser]
+ * Bug 42384: Regression: quickstart doesn't work anymore [tor-browser]
+ * Bug 41058: Update Snowflake to 2.8.1 [tor-browser-build]
+ * Windows + macOS + Linux
+ * Updated Firefox to 115.7.0esr
+ * Bug 41917: Make the appearance of letterboxing look more intentional [tor-browser]
+ * Bug 42338: Changing circuit programmatically in Tor Browser not working anymore! [tor-browser]
+ * Android
+ * Updated GeckoView to 115.7.0esr
+ * Bug 42252: Plumb down TorConnect commands from firefox-android to GeckoView [tor-browser]
+ * Bug 42346: Crash in firefox-android originating in backported FullScreenNotificationDialog patch [tor-browser]
+ * Bug 42353: Fix Android NoScript automatic updates [tor-browser]
+ * Bug 42355: Fullscreen on Android doesn't hide system bars [tor-browser]
+ * Bug 42367: Backport Android security fixes from Firefox 122 [tor-browser]
+ * Bug 42368: Tor Browser 13.5a3 crashes during start-up because of API26+ methods [tor-browser]
+ * Linux
+ * Bug 42293: Updater is disabled when tor-browser is run by torbrowser-launcher flatpak [tor-browser]
+ * Build System
+ * All Platforms
+ * Updated Go to 1.20.13 and 1.21.6
+ * Bug 41037: Set time on signing machine before starting signing [tor-browser-build]
+ * Bug 41059: Update keyring/torbrowser.gpg with updated key [tor-browser-build]
+ * Bug 41063: Run "file $keyring" in tools/keyring/list-all-keyrings [tor-browser-build]
+ * Bug 40067: Use --no-verbose wget option when not running in a terminal [rbm]
+ * Windows
+ * Bug 40606: Use Clang to compile NSIS [tor-browser-build]
+ * Bug 40900: Update NSIS to 3.09 [tor-browser-build]
+ * Bug 41065: Do a cleanup of the NSIS script [tor-browser-build]
+
+Tor Browser 13.0.9 - January 23 2024
+ * All Platforms
+ * Updated Snowflake to 2.8.1
+ * Bug 42363: Tab thumbnails enhancements [tor-browser]
+ * Bug 42365: Rebase Tor Browser Stable onto Firefox 115.7.0esr [tor-browser]
+ * Bug 42367: Backport Android security fixes from Firefox 122 [tor-browser]
+ * Bug 42369: Revert YEC 2023 changes [tor-browser]
+ * Bug 41058: Update Snowflake to 2.8.1 [tor-browser-build]
+ * Windows + macOS + Linux
+ * Updated Firefox to 115.7.0esr
+ * Bug 42099: Blind cross-origin requests to .tor.onion domains [tor-browser]
+ * Bug 42189: Assertion failure: the value of mPrivateBrowsingId in the loadContext and in the loadInfo are not the same! [tor-browser]
+ * Android
+ * Updated GeckoView to 115.7.0esr
+ * Bug 42313: Enable One UI Sans KR as a possible font for Korean (MozBug 1865238) [tor-browser]
+ * Bug 42324: Onion Location on Android is ignored [tor-browser]
+ * Bug 42346: Crash in firefox-android originating in backported FullScreenNotificationDialog patch [tor-browser]
+ * Bug 42353: Fix Android NoScript automatic updates [tor-browser]
+ * Bug 42355: Fullscreen on Android doesn't hide system bars [tor-browser]
+ * Build System
+ * All Platforms
+ * Updated Go to 1.20.13 and 1.21.6
+ * Bug 41059: Update keyring/torbrowser.gpg with updated key [tor-browser-build]
+ * Bug 41063: Run "file $keyring" in tools/keyring/list-all-keyrings [tor-browser-build]
+ * Windows + macOS + Linux
+ * Bug 41056: Make it possible to use templates in var/torbrowser_incremental_from [tor-browser-build]
+ * Windows + macOS
+ * Bug 41016: Switch from bullseye to bookworm for desktop platforms [tor-browser-build]
+ * Windows
+ * Bug 41015: Enable std::filesystem on libc++ on Windows [tor-browser-build]
+ * Android
+ * Bug 41066: The Android x86 APK for 13.0.9 is too big [tor-browser-build]
+
Tor Browser 13.5a3 - December 22 2023
* All Platforms
* Updated Tor to 0.4.8.10
=====================================
projects/browser/allowed_addons.json
=====================================
@@ -17,7 +17,7 @@
"picture_url": "https://addons.mozilla.org/user-media/userpics/34/9734/13299734/13299734.pn…"
}
],
- "average_daily_users": 1113519,
+ "average_daily_users": 1149777,
"categories": {
"firefox": [
"web-development",
@@ -28,7 +28,7 @@
"contributions_url": "https://opencollective.com/darkreader?utm_content=product-page-contribute&u…",
"created": "2017-09-19T07:03:00Z",
"current_version": {
- "id": 5661222,
+ "id": 5678786,
"compatibility": {
"firefox": {
"min": "54.0",
@@ -39,7 +39,7 @@
"max": "*"
}
},
- "edit_url": "https://addons.mozilla.org/en-US/developers/addon/darkreader/versions/56612…",
+ "edit_url": "https://addons.mozilla.org/en-US/developers/addon/darkreader/versions/56787…",
"is_strict_compatibility_enabled": false,
"license": {
"id": 22,
@@ -50,22 +50,22 @@
"url": "http://www.opensource.org/license/mit"
},
"release_notes": {
- "en-US": "- Improved subdomain handling in Site List.\n- Improved dark theme detection.\n- Fixed page crashes (Slack issue).\n- Fixed Site List migration.\n- Reduced image analysis memory usage.\n- Users' fixes for websites."
+ "en-US": "- Improved dark theme detection.\n- Dynamic mode bug fixes.\n- Users' fixes for websites."
},
- "reviewed": "2023-12-08T12:55:44Z",
- "version": "4.9.73",
+ "reviewed": "2024-01-22T11:18:14Z",
+ "version": "4.9.76",
"files": [
{
- "id": 4205543,
- "created": "2023-12-06T15:41:16Z",
- "hash": "sha256:7c399ff32561886bb80dad0cafaf8f629792b0b71ff1efcf12667e05a2b38f1a",
+ "id": 4223104,
+ "created": "2024-01-17T14:17:21Z",
+ "hash": "sha256:d3afe139928c3c30bd11347c08a3360fa3417be4667c47f3de19fdc0ab92da9f",
"is_restart_required": false,
"is_webextension": true,
"is_mozilla_signed_extension": false,
"platform": "all",
- "size": 682962,
+ "size": 723386,
"status": "public",
- "url": "https://addons.mozilla.org/firefox/downloads/file/4205543/darkreader-4.9.73…",
+ "url": "https://addons.mozilla.org/firefox/downloads/file/4223104/darkreader-4.9.76…",
"permissions": [
"alarms",
"contextMenus",
@@ -143,7 +143,7 @@
},
"is_disabled": false,
"is_experimental": false,
- "last_updated": "2023-12-08T12:55:44Z",
+ "last_updated": "2024-01-22T11:18:14Z",
"name": {
"ar": "Dark Reader",
"bn": "Dark Reader",
@@ -218,10 +218,10 @@
"category": "recommended"
},
"ratings": {
- "average": 4.5518,
- "bayesian_average": 4.550675591135547,
- "count": 5306,
- "text_count": 1668
+ "average": 4.5479,
+ "bayesian_average": 4.546785102314431,
+ "count": 5377,
+ "text_count": 1689
},
"ratings_url": "https://addons.mozilla.org/en-US/firefox/addon/darkreader/reviews/",
"requires_payment": false,
@@ -318,7 +318,7 @@
"type": "extension",
"url": "https://addons.mozilla.org/en-US/firefox/addon/darkreader/",
"versions_url": "https://addons.mozilla.org/en-US/firefox/addon/darkreader/versions/",
- "weekly_downloads": 39727
+ "weekly_downloads": 25711
},
"notes": null
},
@@ -334,7 +334,7 @@
"picture_url": "https://addons.mozilla.org/user-media/userpics/56/7656/6937656/6937656.png?…"
}
],
- "average_daily_users": 263643,
+ "average_daily_users": 267473,
"categories": {
"firefox": [
"privacy-security"
@@ -547,10 +547,10 @@
"category": "recommended"
},
"ratings": {
- "average": 4.8027,
- "bayesian_average": 4.798106734548776,
- "count": 1384,
- "text_count": 245
+ "average": 4.8014,
+ "bayesian_average": 4.796833851849327,
+ "count": 1400,
+ "text_count": 250
},
"ratings_url": "https://addons.mozilla.org/en-US/firefox/addon/decentraleyes/reviews/",
"requires_payment": false,
@@ -635,7 +635,7 @@
"type": "extension",
"url": "https://addons.mozilla.org/en-US/firefox/addon/decentraleyes/",
"versions_url": "https://addons.mozilla.org/en-US/firefox/addon/decentraleyes/versions/",
- "weekly_downloads": 3543
+ "weekly_downloads": 3594
},
"notes": null
},
@@ -651,7 +651,7 @@
"picture_url": "https://addons.mozilla.org/user-media/userpics/73/4073/5474073/5474073.png?…"
}
],
- "average_daily_users": 1198252,
+ "average_daily_users": 1220177,
"categories": {
"firefox": [
"privacy-security"
@@ -1170,10 +1170,10 @@
"category": "recommended"
},
"ratings": {
- "average": 4.7991,
- "bayesian_average": 4.796396010098387,
- "count": 2350,
- "text_count": 445
+ "average": 4.796,
+ "bayesian_average": 4.793312997020196,
+ "count": 2377,
+ "text_count": 449
},
"ratings_url": "https://addons.mozilla.org/en-US/firefox/addon/privacy-badger17/reviews/",
"requires_payment": false,
@@ -1197,7 +1197,7 @@
"type": "extension",
"url": "https://addons.mozilla.org/en-US/firefox/addon/privacy-badger17/",
"versions_url": "https://addons.mozilla.org/en-US/firefox/addon/privacy-badger17/versions/",
- "weekly_downloads": 22327
+ "weekly_downloads": 25171
},
"notes": null
},
@@ -1213,7 +1213,7 @@
"picture_url": null
}
],
- "average_daily_users": 7397430,
+ "average_daily_users": 7634996,
"categories": {
"firefox": [
"privacy-security"
@@ -1222,7 +1222,7 @@
"contributions_url": "",
"created": "2015-04-25T07:26:22Z",
"current_version": {
- "id": 5654508,
+ "id": 5672315,
"compatibility": {
"firefox": {
"min": "78.0",
@@ -1233,7 +1233,7 @@
"max": "*"
}
},
- "edit_url": "https://addons.mozilla.org/en-US/developers/addon/ublock-origin/versions/56…",
+ "edit_url": "https://addons.mozilla.org/en-US/developers/addon/ublock-origin/versions/56…",
"is_strict_compatibility_enabled": false,
"license": {
"id": 6,
@@ -1244,23 +1244,24 @@
"url": "http://www.gnu.org/licenses/gpl-3.0.html"
},
"release_notes": {
- "en-US": "See complete release notes for <a href=\"https://prod.outgoing.prod.webservices.mozgcp.net/v1/4c736806dc9702f9496c1c…" rel=\"nofollow\">1.54.0</a>.\n\n<b>Fixes / changes</b>\n\n<ul><li><a href=\"https://prod.outgoing.prod.webservices.mozgcp.net/v1/30ee045a42c04a557ec92d…" rel=\"nofollow\">Enable path for native <code>has()</code> selector in Firefox</a></li><li><a href=\"https://prod.outgoing.prod.webservices.mozgcp.net/v1/26aaa3263afd1e6e450a7f…" rel=\"nofollow\">Allow scriptlets to be injected in <code>about:blank</code></a></li><li><a href=\"https://prod.outgoing.prod.webservices.mozgcp.net/v1/5967388a2432967ee63e77…" rel=\"nofollow\">Fix faulty <code>as</code> vararg in <code>set-constant</code> scriptlet</a></li><li><a href=\"https://prod.outgoing.prod.webservices.mozgcp.net/v1/b9a3ce2fd67895cc3fd06f…" rel=\"nofollow\">Add support to redirect to <code>noop.json</code></a></li><li><a href=\"https://prod.outgoing.prod.webservices.mozgcp.net/v1/1a7fcce826cb83449490e3…" rel=\"nofollow\">More improvements to the <code>google-ima</code> shim script</a> (by @kzar)</li><li><a href=\"https://prod.outgoing.prod.webservices.mozgcp.net/v1/56d921f7e251fb313a4be0…" rel=\"nofollow\">All exceptions filters are exempt from requiring a trusted source</a></li><li><a href=\"https://prod.outgoing.prod.webservices.mozgcp.net/v1/b3b9c520dd7fef26a4f129…" rel=\"nofollow\">Add <code>trusted-set-session-storage-item</code> scriptlet</a></li><li><a href=\"https://prod.outgoing.prod.webservices.mozgcp.net/v1/5f347a4a217555ac7ff920…" rel=\"nofollow\">Allow the use of quotes in <code>set-cookie</code> scriptlet </a></li><li><a href=\"https://prod.outgoing.prod.webservices.mozgcp.net/v1/fe9490248b43262e2613b2…" rel=\"nofollow\">Allow the use of quotes in <code>set-(local|session)-storage-item</code></a></li><li><a href=\"https://prod.outgoing.prod.webservices.mozgcp.net/v1/92d58a934e2392a346a587…" rel=\"nofollow\">Add ability to trigger cookie removal on specific events</a></li><li><a href=\"https://prod.outgoing.prod.webservices.mozgcp.net/v1/23e952e408915752c90dc3…" rel=\"nofollow\">Ensure CSSTree does not hold a reference onto last parsed string</a></li><li><a href=\"https://prod.outgoing.prod.webservices.mozgcp.net/v1/302676f334820cdfe567f7…" rel=\"nofollow\">Lower minimum Expires value to 4h</a></li><li><a href=\"https://prod.outgoing.prod.webservices.mozgcp.net/v1/03ac48dee7ecbf33ac2dd4…" rel=\"nofollow\">Properly reset needle length in unserialized buffer</a></li><li><a href=\"https://prod.outgoing.prod.webservices.mozgcp.net/v1/d4babab0e0c4b624992f8f…" rel=\"nofollow\">Add additional flags to regional lists</a> (by @DandelionSprout)</li><li><a href=\"https://prod.outgoing.prod.webservices.mozgcp.net/v1/a09bd04e017892dd0b0d12…" rel=\"nofollow\">Harden scriptlets which need to serialize function code into string</a></li><li><a href=\"https://prod.outgoing.prod.webservices.mozgcp.net/v1/1a5be5c8aa0baa49879f92…" rel=\"nofollow\">Reset <code>g</code> regexes before use in <code>rmnt</code>/<code>rpnt</code> scriptlets</a></li><li><a href=\"https://prod.outgoing.prod.webservices.mozgcp.net/v1/f2e3dd373c3a474ca27bad…" rel=\"nofollow\">Apply response filtering according to mime type</a></li><li><a href=\"https://prod.outgoing.prod.webservices.mozgcp.net/v1/12cfcbade6a208e02352fd…" rel=\"nofollow\">Add t/f to set-cookie</a> (by @ryanbr)</li><li><a href=\"https://prod.outgoing.prod.webservices.mozgcp.net/v1/7856310df6fe39bff4e1b0…" rel=\"nofollow\">Have <code>urltransform=</code> use the same syntax as <code>replace=</code></a></li><li><a href=\"https://prod.outgoing.prod.webservices.mozgcp.net/v1/520b2f8c295d638b0c72f5…" rel=\"nofollow\">Implement network filter option <code>replace=</code></a></li><li>...</li></ul>\n<a href=\"https://prod.outgoing.prod.webservices.mozgcp.net/v1/3f4f5634b3bdd26c8e335f…" rel=\"nofollow\">Commits history since last version</a>"
+ "en-US": "See complete release notes for <a href=\"https://prod.outgoing.prod.webservices.mozgcp.net/v1/514b85ddd154153a63fe9c…" rel=\"nofollow\">1.55.0</a>.\n\n<b>Fixes / changes</b>\n\n<ul><li><a href=\"https://prod.outgoing.prod.webservices.mozgcp.net/v1/1e03af965f6b7a76aa94f6…" rel=\"nofollow\">Mind drop events in filter expression field of logger</a></li><li><a href=\"https://prod.outgoing.prod.webservices.mozgcp.net/v1/e018352ca30c61b4a80c2a…" rel=\"nofollow\">Improve <code>xml-prune</code> scriptlet</a></li><li><a href=\"https://prod.outgoing.prod.webservices.mozgcp.net/v1/ec6b213ac8c38077b676e1…" rel=\"nofollow\">Fix message entries overflowing in logger</a></li><li><a href=\"https://prod.outgoing.prod.webservices.mozgcp.net/v1/a6311ada7aec5e36a802c2…" rel=\"nofollow\">Add support for <code>application/x-javascript</code> in <code>replace=</code> option</a></li><li><a href=\"https://prod.outgoing.prod.webservices.mozgcp.net/v1/8b0f4ac6d1a68a10f0736a…" rel=\"nofollow\">Extend support for differential updates to imported lists</a></li><li><a href=\"https://prod.outgoing.prod.webservices.mozgcp.net/v1/5e2218ad38a67bad16b5a2…" rel=\"nofollow\">Add detection of mismatched <code>!#if</code>-<code>!#endif</code> in linter</a></li><li><a href=\"https://prod.outgoing.prod.webservices.mozgcp.net/v1/d3d5708132bbca2b9b3232…" rel=\"nofollow\">Support links to update lists which are differential update-friendly</a></li><li><a href=\"https://prod.outgoing.prod.webservices.mozgcp.net/v1/5da8dae3bfc5fd15895013…" rel=\"nofollow\">Remove \"Purge all caches\" button from \"Filter lists\" pane</a></li><li><a href=\"https://prod.outgoing.prod.webservices.mozgcp.net/v1/f9bd0d08194525f2457cf5…" rel=\"nofollow\">Add support for <code>all</code> list token in updater-link feature</a></li><li><a href=\"https://prod.outgoing.prod.webservices.mozgcp.net/v1/f266c7ca3a6228a20999be…" rel=\"nofollow\">Fix logging of broad exception filter <code>#@#+js()</code></a></li><li><a href=\"https://prod.outgoing.prod.webservices.mozgcp.net/v1/444dcf1f11a8dacef0553e…" rel=\"nofollow\">Improve <code>no-xhr-if</code> scriptlet</a></li><li><a href=\"https://prod.outgoing.prod.webservices.mozgcp.net/v1/5f699ca11537ba17c330a8…" rel=\"nofollow\">Ensure cache storage backend is selected before access</a></li><li><a href=\"https://prod.outgoing.prod.webservices.mozgcp.net/v1/983fbc3b50419c274040d9…" rel=\"nofollow\">Fix popup panel rendering when embedded in logger</a></li><li><a href=\"https://prod.outgoing.prod.webservices.mozgcp.net/v1/2f972ff52f4edc3dc99084…" rel=\"nofollow\">Add visual hint in support information re. differential update</a></li><li><a href=\"https://prod.outgoing.prod.webservices.mozgcp.net/v1/75541b4012443bd5602cc0…" rel=\"nofollow\">Remove obsolete web accessible resources</a></li><li><a href=\"https://prod.outgoing.prod.webservices.mozgcp.net/v1/8eb76fbc2577032e63698e…" rel=\"nofollow\">Rename <code>urltransform</code> to <code>uritransform</code></a></li><li><a href=\"https://prod.outgoing.prod.webservices.mozgcp.net/v1/43e266ca8d07228388c2a6…" rel=\"nofollow\">Vertically expand/collapse in steps in dom inspector</a></li><li><a href=\"https://prod.outgoing.prod.webservices.mozgcp.net/v1/d1f0669c5cf9357a9528d8…" rel=\"nofollow\">Reset the DOM inspector when URL in top context changes</a></li><li><a href=\"https://prod.outgoing.prod.webservices.mozgcp.net/v1/d2f70a310ccc2ce2b2c97c…" rel=\"nofollow\">Support shadow-piercing combinator <code>>>></code> in <code>trusted-click-element</code></a></li><li>[...]</li></ul>\n<a href=\"https://prod.outgoing.prod.webservices.mozgcp.net/v1/7d13ab8046ad75d1230ea5…" rel=\"nofollow\">Commits history since last version</a>"
},
- "reviewed": "2023-11-27T08:08:01Z",
- "version": "1.54.0",
+ "reviewed": "2024-01-08T10:26:54Z",
+ "version": "1.55.0",
"files": [
{
- "id": 4198829,
- "created": "2023-11-22T16:24:35Z",
- "hash": "sha256:9797160908191710ff0858536ba6dc29ecad9923c30b2ad6d3e5e371d759e44d",
+ "id": 4216633,
+ "created": "2024-01-03T20:24:50Z",
+ "hash": "sha256:a02ca1d32737c3437f97553e5caaead6479a66ac1f8ff3b84a06cfa6bb0c7647",
"is_restart_required": false,
"is_webextension": true,
"is_mozilla_signed_extension": false,
"platform": "all",
- "size": 3630690,
+ "size": 3647341,
"status": "public",
- "url": "https://addons.mozilla.org/firefox/downloads/file/4198829/ublock_origin-1.5…",
+ "url": "https://addons.mozilla.org/firefox/downloads/file/4216633/ublock_origin-1.5…",
"permissions": [
+ "alarms",
"dns",
"menus",
"privacy",
@@ -1378,7 +1379,7 @@
},
"is_disabled": false,
"is_experimental": false,
- "last_updated": "2023-12-18T15:55:24Z",
+ "last_updated": "2024-01-21T19:40:21Z",
"name": {
"ar": "uBlock Origin",
"bg": "uBlock Origin",
@@ -1523,10 +1524,10 @@
"category": "recommended"
},
"ratings": {
- "average": 4.7863,
- "bayesian_average": 4.785924647292365,
- "count": 16885,
- "text_count": 4402
+ "average": 4.7869,
+ "bayesian_average": 4.786526880140991,
+ "count": 17099,
+ "text_count": 4466
},
"ratings_url": "https://addons.mozilla.org/en-US/firefox/addon/ublock-origin/reviews/",
"requires_payment": false,
@@ -1589,7 +1590,7 @@
"type": "extension",
"url": "https://addons.mozilla.org/en-US/firefox/addon/ublock-origin/",
"versions_url": "https://addons.mozilla.org/en-US/firefox/addon/ublock-origin/versions/",
- "weekly_downloads": 181326
+ "weekly_downloads": 191212
},
"notes": null
},
@@ -1605,7 +1606,7 @@
"picture_url": null
}
],
- "average_daily_users": 174830,
+ "average_daily_users": 177037,
"categories": {
"firefox": [
"photos-music-videos",
@@ -1701,10 +1702,10 @@
"category": "recommended"
},
"ratings": {
- "average": 4.4823,
- "bayesian_average": 4.47726114447234,
- "count": 1161,
- "text_count": 436
+ "average": 4.4783,
+ "bayesian_average": 4.473306026343802,
+ "count": 1177,
+ "text_count": 445
},
"ratings_url": "https://addons.mozilla.org/en-US/firefox/addon/video-background-play-fix/re…",
"requires_payment": false,
@@ -1726,7 +1727,7 @@
"type": "extension",
"url": "https://addons.mozilla.org/en-US/firefox/addon/video-background-play-fix/",
"versions_url": "https://addons.mozilla.org/en-US/firefox/addon/video-background-play-fix/ve…",
- "weekly_downloads": 379
+ "weekly_downloads": 433
},
"notes": null
},
@@ -1742,7 +1743,7 @@
"picture_url": null
}
],
- "average_daily_users": 85074,
+ "average_daily_users": 81898,
"categories": {
"firefox": [
"privacy-security",
@@ -1852,10 +1853,10 @@
],
"promoted": null,
"ratings": {
- "average": 4.3766,
- "bayesian_average": 4.362648333186986,
- "count": 401,
- "text_count": 112
+ "average": 4.3802,
+ "bayesian_average": 4.366169675126323,
+ "count": 405,
+ "text_count": 113
},
"ratings_url": "https://addons.mozilla.org/en-US/firefox/addon/privacy-possum/reviews/",
"requires_payment": false,
@@ -1877,7 +1878,7 @@
"type": "extension",
"url": "https://addons.mozilla.org/en-US/firefox/addon/privacy-possum/",
"versions_url": "https://addons.mozilla.org/en-US/firefox/addon/privacy-possum/versions/",
- "weekly_downloads": 965
+ "weekly_downloads": 1389
},
"notes": null
},
@@ -1893,7 +1894,7 @@
"picture_url": "https://addons.mozilla.org/user-media/userpics/64/9064/12929064/12929064.pn…"
}
],
- "average_daily_users": 288929,
+ "average_daily_users": 299174,
"categories": {
"firefox": [
"search-tools",
@@ -1904,7 +1905,7 @@
"contributions_url": "https://www.paypal.com/donate?hosted_button_id=GLL4UNSNU6SQN&utm_content=pr…",
"created": "2017-06-17T15:23:33Z",
"current_version": {
- "id": 5645237,
+ "id": 5665608,
"compatibility": {
"firefox": {
"min": "115.0",
@@ -1915,7 +1916,7 @@
"max": "*"
}
},
- "edit_url": "https://addons.mozilla.org/en-US/developers/addon/search_by_image/versions/…",
+ "edit_url": "https://addons.mozilla.org/en-US/developers/addon/search_by_image/versions/…",
"is_strict_compatibility_enabled": false,
"license": {
"id": 6,
@@ -1928,20 +1929,20 @@
"release_notes": {
"en-US": "Learn more about this release from the <a href=\"https://prod.outgoing.prod.webservices.mozgcp.net/v1/d50855f24f77fa6f2614b9…" rel=\"nofollow\">changelog</a>."
},
- "reviewed": "2023-11-07T07:33:21Z",
- "version": "6.1.0",
+ "reviewed": "2023-12-19T14:03:13Z",
+ "version": "6.1.1",
"files": [
{
- "id": 4189577,
- "created": "2023-11-02T18:15:34Z",
- "hash": "sha256:1de51c7522b8bf3aca5c2bc4fbd94f5fb092d4418ea8fe4583c8dff2b71b4209",
+ "id": 4209928,
+ "created": "2023-12-17T01:28:51Z",
+ "hash": "sha256:254d78084e332190a2b6ccb1959a42257bdc287addc0685419fcde7df1a52e76",
"is_restart_required": false,
"is_webextension": true,
"is_mozilla_signed_extension": false,
"platform": "all",
- "size": 1156452,
+ "size": 1165289,
"status": "public",
- "url": "https://addons.mozilla.org/firefox/downloads/file/4189577/search_by_image-6…",
+ "url": "https://addons.mozilla.org/firefox/downloads/file/4209928/search_by_image-6…",
"permissions": [
"alarms",
"contextMenus",
@@ -1984,7 +1985,7 @@
},
"is_disabled": false,
"is_experimental": false,
- "last_updated": "2023-11-07T07:33:21Z",
+ "last_updated": "2023-12-19T14:03:13Z",
"name": {
"en-US": "Search by Image"
},
@@ -2110,10 +2111,10 @@
"category": "recommended"
},
"ratings": {
- "average": 4.651,
- "bayesian_average": 4.646505118537081,
- "count": 1361,
- "text_count": 264
+ "average": 4.6458,
+ "bayesian_average": 4.641373152099238,
+ "count": 1389,
+ "text_count": 269
},
"ratings_url": "https://addons.mozilla.org/en-US/firefox/addon/search_by_image/reviews/",
"requires_payment": false,
@@ -2134,7 +2135,7 @@
"type": "extension",
"url": "https://addons.mozilla.org/en-US/firefox/addon/search_by_image/",
"versions_url": "https://addons.mozilla.org/en-US/firefox/addon/search_by_image/versions/",
- "weekly_downloads": 6399
+ "weekly_downloads": 6874
},
"notes": null
},
@@ -2157,7 +2158,7 @@
"picture_url": null
}
],
- "average_daily_users": 118743,
+ "average_daily_users": 123628,
"categories": {
"firefox": [
"search-tools",
@@ -2438,10 +2439,10 @@
"category": "recommended"
},
"ratings": {
- "average": 4.3703,
- "bayesian_average": 4.365894611018555,
- "count": 1288,
- "text_count": 364
+ "average": 4.3745,
+ "bayesian_average": 4.37014166071391,
+ "count": 1311,
+ "text_count": 371
},
"ratings_url": "https://addons.mozilla.org/en-US/firefox/addon/google-search-fixer/reviews/",
"requires_payment": false,
@@ -2461,7 +2462,7 @@
"type": "extension",
"url": "https://addons.mozilla.org/en-US/firefox/addon/google-search-fixer/",
"versions_url": "https://addons.mozilla.org/en-US/firefox/addon/google-search-fixer/versions/",
- "weekly_downloads": 83
+ "weekly_downloads": 52
},
"notes": null
},
@@ -2477,7 +2478,7 @@
"picture_url": "https://addons.mozilla.org/user-media/userpics/43/0143/143/143.png?modified…"
}
],
- "average_daily_users": 313134,
+ "average_daily_users": 313064,
"categories": {
"firefox": [
"web-development",
@@ -2664,10 +2665,10 @@
"category": "recommended"
},
"ratings": {
- "average": 4.3967,
- "bayesian_average": 4.394045030071559,
- "count": 2153,
- "text_count": 831
+ "average": 4.3947,
+ "bayesian_average": 4.3920505434632835,
+ "count": 2171,
+ "text_count": 837
},
"ratings_url": "https://addons.mozilla.org/en-US/firefox/addon/noscript/reviews/",
"requires_payment": false,
@@ -2711,7 +2712,7 @@
"type": "extension",
"url": "https://addons.mozilla.org/en-US/firefox/addon/noscript/",
"versions_url": "https://addons.mozilla.org/en-US/firefox/addon/noscript/versions/",
- "weekly_downloads": 7965
+ "weekly_downloads": 7762
},
"notes": null
},
@@ -2727,7 +2728,7 @@
"picture_url": null
}
],
- "average_daily_users": 158407,
+ "average_daily_users": 162394,
"categories": {
"firefox": [
"photos-music-videos",
@@ -2836,10 +2837,10 @@
"category": "recommended"
},
"ratings": {
- "average": 3.8702,
- "bayesian_average": 3.8661363785150384,
- "count": 1202,
- "text_count": 435
+ "average": 3.8734,
+ "bayesian_average": 3.869354081107614,
+ "count": 1216,
+ "text_count": 441
},
"ratings_url": "https://addons.mozilla.org/en-US/firefox/addon/youtube-high-definition/revi…",
"requires_payment": false,
@@ -2858,7 +2859,7 @@
"type": "extension",
"url": "https://addons.mozilla.org/en-US/firefox/addon/youtube-high-definition/",
"versions_url": "https://addons.mozilla.org/en-US/firefox/addon/youtube-high-definition/vers…",
- "weekly_downloads": 1957
+ "weekly_downloads": 3206
},
"notes": null
}
=====================================
projects/browser/config
=====================================
@@ -99,9 +99,9 @@ input_files:
- URL: https://addons.mozilla.org/firefox/downloads/file/4206186/noscript-11.4.29.…
name: noscript
sha256sum: 05b98840b05ef2acbac333543e4b7c3d40fee2ce5fb4e29260b05e2ff6fe24cd
- - URL: https://addons.mozilla.org/firefox/downloads/file/4198829/ublock_origin-1.5…
+ - URL: https://addons.mozilla.org/firefox/downloads/file/4216633/ublock_origin-1.5…
name: ublock-origin
- sha256sum: 9797160908191710ff0858536ba6dc29ecad9923c30b2ad6d3e5e371d759e44d
+ sha256sum: a02ca1d32737c3437f97553e5caaead6479a66ac1f8ff3b84a06cfa6bb0c7647
enable: '[% c("var/mullvad-browser") %]'
- URL: https://cdn.mullvad.net/browser-extension/0.8.4/mullvad-browser-extension-0…
name: mullvad-extension
=====================================
projects/firefox-android/config
=====================================
@@ -16,7 +16,7 @@ container:
var:
fenix_version: 115.2.1
browser_branch: 13.5-1
- browser_build: 4
+ browser_build: 5
variant: Beta
# This should be updated when the list of gradle dependencies is changed.
gradle_dependencies_version: 1
=====================================
projects/firefox/config
=====================================
@@ -18,7 +18,7 @@ var:
firefox_version: '[% c("var/firefox_platform_version") %]esr'
browser_series: '13.5'
browser_branch: '[% c("var/browser_series") %]-1'
- browser_build: 1
+ browser_build: 2
branding_directory_prefix: 'tb'
copyright_year: '[% exec("git show -s --format=%ci").remove("-.*") %]'
nightly_updates_publish_dir: '[% c("var/nightly_updates_publish_dir_prefix") %]nightly-[% c("var/osname") %]'
=====================================
projects/geckoview/config
=====================================
@@ -16,7 +16,7 @@ container:
var:
geckoview_version: 115.7.0esr
browser_branch: 13.5-1
- browser_build: 1
+ browser_build: 2
copyright_year: '[% exec("git show -s --format=%ci").remove("-.*") %]'
gitlab_project: https://gitlab.torproject.org/tpo/applications/tor-browser
git_commit: '[% exec("git rev-parse HEAD") %]'
=====================================
projects/go/config
=====================================
@@ -1,5 +1,5 @@
# vim: filetype=yaml sw=2
-version: '[% IF c("var/use_go_1_20") %]1.20.12[% ELSE %]1.21.5[% END %]'
+version: '[% IF c("var/use_go_1_20") %]1.20.13[% ELSE %]1.21.6[% END %]'
filename: '[% project %]-[% c("version") %]-[% c("var/osname") %]-[% c("var/build_id") %].tar.[% c("compress_tar") %]'
container:
use_container: 1
@@ -121,11 +121,11 @@ input_files:
enable: '[% ! c("var/linux") %]'
- URL: 'https://go.dev/dl/go[% c("version") %].src.tar.gz'
name: go
- sha256sum: 285cbbdf4b6e6e62ed58f370f3f6d8c30825d6e56c5853c66d3c23bcdb09db19
+ sha256sum: 124926a62e45f78daabbaedb9c011d97633186a33c238ffc1e25320c02046248
enable: '[% !c("var/use_go_1_20") %]'
- URL: 'https://go.dev/dl/go[% c("version") %].src.tar.gz'
name: go
- sha256sum: c5bf934751d31c315c1d0bb5fb02296545fa6d08923566f7a5afec81f2ed27d6
+ sha256sum: 0fe745c530f2f1d67193af3c5ea25246be077989ec5178df266e975f3532449e
enable: '[% c("var/use_go_1_20") %]'
- project: go-bootstrap
name: go-bootstrap
=====================================
projects/manual/config
=====================================
@@ -1,7 +1,7 @@
# vim: filetype=yaml sw=2
# To update, see doc/how-to-update-the-manual.txt
# Remember to update also the package's hash, with the version!
-version: 122062
+version: 136210
filename: 'manual-[% c("version") %]-[% c("var/build_id") %].tar.[% c("compress_tar") %]'
container:
use_container: 1
@@ -23,6 +23,6 @@ input_files:
- project: container-image
- URL: 'https://build-sources.tbb.torproject.org/manual_[% c("version") %].zip'
name: manual
- sha256sum: d51ebe27077817bcdabc0b5616c0c58fc14ea6d06f1a0b459051d67a4c13c348
+ sha256sum: 6731381fd992cf65dd01e56e2b924005af633369da5ac9eb905fd8025255b386
- filename: packagemanual.py
name: package_script
=====================================
projects/translation/config
=====================================
@@ -12,13 +12,13 @@ compress_tar: 'gz'
steps:
base-browser:
base-browser: '[% INCLUDE build %]'
- git_hash: 5490489a8d356a44d792300b4dfddba792d10f2e
+ git_hash: cbd9b6c415ec2edb99237ef67ccd4f033a7b9c2a
targets:
nightly:
git_hash: 'base-browser'
tor-browser:
tor-browser: '[% INCLUDE build %]'
- git_hash: e92772b4a11ced855c27eafd299cf972bef5cd8f
+ git_hash: 799998ee13be225222afc6cfda1687cf63d6cc9e
targets:
nightly:
git_hash: 'tor-browser'
@@ -32,7 +32,7 @@ steps:
fenix: '[% INCLUDE build %]'
# We need to bump the commit before releasing but just pointing to a branch
# might cause too much rebuidling of the Firefox part.
- git_hash: 38741697dc418d7ea90e67cab30ae7cfa4b9c858
+ git_hash: 9622d5c3f3ffd2400fc1bbd4bb7c507f257f9bbb
compress_tar: 'zst'
targets:
nightly:
=====================================
projects/zlib/config
=====================================
@@ -1,6 +1,6 @@
# vim: filetype=yaml sw=2
filename: '[% project %]-[% c("version") %]-[% c("var/osname") %]-[% c("var/build_id") %].tar.[% c("compress_tar") %]'
-version: '1.3'
+version: '1.3.1'
git_hash: 'v[% c("version") %]'
git_url: https://github.com/madler/zlib.git
gpg_keyring: zlib.gpg
=====================================
rbm.conf
=====================================
@@ -81,12 +81,12 @@ buildconf:
git_signtag_opt: '-s'
var:
- torbrowser_version: '13.5a3'
- torbrowser_build: 'build2'
+ torbrowser_version: '13.5a4'
+ torbrowser_build: 'build1'
torbrowser_incremental_from:
- - '13.0a6'
- '13.5a1'
- '13.5a2'
+ - '13.5a3'
updater_enabled: 1
build_mar: 1
mar_channel_id: '[% c("var/projectname") %]-torproject-[% c("var/channel") %]'
View it on GitLab: https://gitlab.torproject.org/tpo/applications/tor-browser-build/-/commit/e…
--
View it on GitLab: https://gitlab.torproject.org/tpo/applications/tor-browser-build/-/commit/e…
You're receiving this email because of your account on gitlab.torproject.org.
[View Less]
1
0

[Git][tpo/applications/tor-browser-build][main] Bug 41065: Cleanup the NSIS script
by Pier Angelo Vendrame (@pierov) 29 Jan '24
by Pier Angelo Vendrame (@pierov) 29 Jan '24
29 Jan '24
Pier Angelo Vendrame pushed to branch main at The Tor Project / Applications / tor-browser-build
Commits:
1a571c59 by Pier Angelo Vendrame at 2024-01-29T10:16:12+01:00
Bug 41065: Cleanup the NSIS script
Improve the formatting of the installer, and update the language list
to match the one in rbm.conf (even though it would be good to keep the
lists synchronized automatically).
Also, include the channel name in the displayed name and in the default
install directory (except for release).
…
[View More]Since we are changing many lines, I took the ocasion to switch to LF
line endings (NSIS accepts them).
- - - - -
2 changed files:
- projects/browser/build
- projects/browser/windows-installer.nsi
Changes:
=====================================
projects/browser/build
=====================================
@@ -305,11 +305,6 @@ done
cat > $distdir/windows-installer/browser-portable.nsi << 'BROWSER_NSI'
[% INCLUDE 'windows-installer.nsi' %]
BROWSER_NSI
- [% IF c('var/mullvad-browser') -%]
- cat > $distdir/windows-installer/browser-system.nsi << 'BROWSER_NSI'
-[% INCLUDE 'windows-installer.nsi' system_install_mode = 1 %]
-BROWSER_NSI
- [% END -%]
mv ${TB_STAGE_DIR} $distdir/windows-installer/"[% c('var/Project_Name') %]"
mv $distdir/windows-installer ${TB_STAGE_DIR}
[% END %]
@@ -389,11 +384,6 @@ cd $distdir
# Working around NSIS braindamage
python3 $rootdir/pe_checksum_fix.py browser-install.exe
mv browser-install.exe $OUTDIR/[% c("var/project-name") %]-[% c("var/osname") %]-portable-[% c("var/torbrowser_version") %].exe
- [% IF c('var/mullvad-browser') -%]
- makensis browser-system.nsi
- python3 $rootdir/pe_checksum_fix.py browser-install.exe
- mv browser-install.exe $OUTDIR/[% c("var/project-name") %]-[% c("var/osname") %]-install-[% c("var/torbrowser_version") %].exe
- [% END -%]
popd
[% END %]
rm -rf $distdir/${PKG_DIR}
=====================================
projects/browser/windows-installer.nsi
=====================================
@@ -1,248 +1,169 @@
-;NSIS Installer for Tor/Base/Mullvad Browser
-;Written by Moritz Bartl
-;released under Public Domain
-
-;--------------------------------
-;Modern UI
-
- !include "FileFunc.nsh"
- !include "MUI2.nsh"
- !include "LogicLib.nsh"
- !include "WinVer.nsh"
-
-;--------------------------------
-;General
-
- ;Location of Tor/Base/Mullvad Browser to put into installer
- !define PROGRAM_SOURCE ".\[% c('var/Project_Name') %]\"
-
- Name "[% c('var/Project_Name') %]"
- OutFile "browser-install.exe"
-
- ;Default installation folder
-[% IF system_install_mode -%]
- InstallDir "$PROGRAMFILES\[% c('var/Project_Name') %]"
-[% ELSE -%]
- InstallDir "$DESKTOP\[% c('var/Project_Name') %]"
-[% END -%]
-
- ;Best (but slowest) compression
- SetCompressor /SOLID lzma
- SetCompressorDictSize 32
-
- ;Request application privileges for Windows Vista
-[% IF system_install_mode -%]
- RequestExecutionLevel admin
-[% ELSE -%]
- RequestExecutionLevel user
-[% END -%]
-
- ;Support HiDPI displays
- ManifestDPIAware true
-
-[% IF system_install_mode -%]
- ;Registry keys to uninstall system-wide installs
- !define UNINST_KEY "Software\Microsoft\Windows\CurrentVersion\Uninstall\[% c('var/ProjectName') %]"
-[% END -%]
-
-;--------------------------------
-;Metadata
-
- VIProductVersion "[% pc("firefox", "var/browser_series") %].0.0"
- VIAddVersionKey "ProductName" "[% c('var/Project_Name') %]"
- VIAddVersionKey "ProductVersion" "[% c('var/torbrowser_version') %]"
- VIAddVersionKey "FileDescription" "[% c('var/Project_Name') %][% IF system_install_mode -%] System[% END -%] Installer"
- VIAddVersionKey "LegalCopyright" "© [% pc("firefox", "var/copyright_year") %] [% IF c('var/mullvad-browser') -%]Mullvad, Tor Browser and Mozilla Developers[% ELSE -%]The Tor Project[% END -%]"
-
-;--------------------------------
-;Interface Configuration
-
- !define MUI_ICON "[% c('var/projectname') %][% IF !c('var/base-browser') -%]-[% c('var/channel') %][% END -%].ico"
- !define MUI_ABORTWARNING
-
-;--------------------------------
-;Modern UI settings
- !define MUI_FINISHPAGE_NOREBOOTSUPPORT ; we don't require a reboot
- !define MUI_FINISHPAGE_RUN
- !define MUI_FINISHPAGE_RUN_FUNCTION "StartBrowser"
- !define MUI_FINISHPAGE_SHOWREADME ; misuse for option to create shortcut; less ugly than MUI_PAGE_COMPONENTS
- !define MUI_FINISHPAGE_SHOWREADME_TEXT "&Add Start Menu && Desktop shortcuts"
- !define MUI_FINISHPAGE_SHOWREADME_FUNCTION "CreateShortCuts"
-;--------------------------------
-;Pages
-
- !define MUI_PAGE_CUSTOMFUNCTION_LEAVE CheckIfTargetDirectoryExists
- !insertmacro MUI_PAGE_DIRECTORY
- !insertmacro MUI_PAGE_INSTFILES
- !insertmacro MUI_PAGE_FINISH
-
-;--------------------------------
-;Languages
-
- !insertmacro MUI_LANGUAGE "English" ;first language is the default language
- !insertmacro MUI_LANGUAGE "French"
- !insertmacro MUI_LANGUAGE "German"
- !insertmacro MUI_LANGUAGE "Spanish"
- !insertmacro MUI_LANGUAGE "SpanishInternational"
- !insertmacro MUI_LANGUAGE "SimpChinese"
- !insertmacro MUI_LANGUAGE "TradChinese"
- !insertmacro MUI_LANGUAGE "Japanese"
- !insertmacro MUI_LANGUAGE "Korean"
- !insertmacro MUI_LANGUAGE "Italian"
- !insertmacro MUI_LANGUAGE "Dutch"
- !insertmacro MUI_LANGUAGE "Danish"
- !insertmacro MUI_LANGUAGE "Swedish"
- !insertmacro MUI_LANGUAGE "Norwegian"
- !insertmacro MUI_LANGUAGE "NorwegianNynorsk"
- !insertmacro MUI_LANGUAGE "Finnish"
- !insertmacro MUI_LANGUAGE "Greek"
- !insertmacro MUI_LANGUAGE "Russian"
- !insertmacro MUI_LANGUAGE "Portuguese"
- !insertmacro MUI_LANGUAGE "PortugueseBR"
- !insertmacro MUI_LANGUAGE "Polish"
- !insertmacro MUI_LANGUAGE "Ukrainian"
- !insertmacro MUI_LANGUAGE "Czech"
- !insertmacro MUI_LANGUAGE "Slovak"
- !insertmacro MUI_LANGUAGE "Croatian"
- !insertmacro MUI_LANGUAGE "Bulgarian"
- !insertmacro MUI_LANGUAGE "Hungarian"
- !insertmacro MUI_LANGUAGE "Thai"
- !insertmacro MUI_LANGUAGE "Romanian"
- !insertmacro MUI_LANGUAGE "Latvian"
- !insertmacro MUI_LANGUAGE "Macedonian"
- !insertmacro MUI_LANGUAGE "Estonian"
- !insertmacro MUI_LANGUAGE "Turkish"
- !insertmacro MUI_LANGUAGE "Lithuanian"
- !insertmacro MUI_LANGUAGE "Slovenian"
- !insertmacro MUI_LANGUAGE "Serbian"
- !insertmacro MUI_LANGUAGE "SerbianLatin"
- !insertmacro MUI_LANGUAGE "Arabic"
- !insertmacro MUI_LANGUAGE "Farsi"
- !insertmacro MUI_LANGUAGE "Hebrew"
- !insertmacro MUI_LANGUAGE "Indonesian"
- !insertmacro MUI_LANGUAGE "Mongolian"
- !insertmacro MUI_LANGUAGE "Luxembourgish"
- !insertmacro MUI_LANGUAGE "Albanian"
- !insertmacro MUI_LANGUAGE "Breton"
- !insertmacro MUI_LANGUAGE "Belarusian"
- !insertmacro MUI_LANGUAGE "Icelandic"
- !insertmacro MUI_LANGUAGE "Malay"
- !insertmacro MUI_LANGUAGE "Bosnian"
- !insertmacro MUI_LANGUAGE "Kurdish"
- !insertmacro MUI_LANGUAGE "Irish"
- !insertmacro MUI_LANGUAGE "Uzbek"
- !insertmacro MUI_LANGUAGE "Galician"
- !insertmacro MUI_LANGUAGE "Afrikaans"
- !insertmacro MUI_LANGUAGE "Catalan"
- !insertmacro MUI_LANGUAGE "Esperanto"
-
-;--------------------------------
-;Multi Language support: Read strings from separate file
-
-; !include [% c('var/projectname') %]-langstrings.nsi
-
-;--------------------------------
-;Reserve Files
-
- ;If you are using solid compression, files that are required before
- ;the actual installation should be stored first in the data block,
- ;because this will make your installer start faster.
-
- !insertmacro MUI_RESERVEFILE_LANGDLL
-
-;--------------------------------
-;Installer Sections
-
-Section "[% c('var/Project_Name') %]" SecBrowser
-
- SetOutPath "$INSTDIR"
-[% IF !system_install_mode -%]
- File /r "${PROGRAM_SOURCE}\*.*"
- CreateShortCut "$INSTDIR\Start [% c('var/Project_Name') %].lnk" "$INSTDIR\Browser\[% c('var/exe_name') %].exe"
-[% ELSE -%]
- File /r "${PROGRAM_SOURCE}\Browser\*.*"
-
- ;Enable system-wide install in the browser
- FileOpen $0 "$INSTDIR\system-install" w
- FileClose $0
-
- ;Write the uninstaller
- WriteUninstaller $INSTDIR\uninstall.exe
-
- ;Add the uninstaller to the control panel
- WriteRegStr HKLM "${UNINST_KEY}" "DisplayName" "[% c('var/Project_Name') %]"
- WriteRegStr HKLM "${UNINST_KEY}" "UninstallString" "$\"$INSTDIR\uninstall.exe$\""
- WriteRegStr HKLM "${UNINST_KEY}" "QuietUninstallString" "$\"$INSTDIR\uninstall.exe$\" /S"
- WriteRegStr HKLM "${UNINST_KEY}" "Publisher" "[% IF c('var/mullvad-browser') -%]Mullvad VPN[% ELSE -%]The Tor Project[% END -%]"
- WriteRegStr HKLM "${UNINST_KEY}" "DisplayIcon" "$\"$INSTDIR\[% c('var/exe_name') %].exe$\""
- WriteRegStr HKLM "${UNINST_KEY}" "DisplayVersion" "[% c('var/torbrowser_version') %]"
- WriteRegDWORD HKLM "${UNINST_KEY}" "NoModify" "1"
- WriteRegDWORD HKLM "${UNINST_KEY}" "NoRepair" "1"
- ${GetSize} "$INSTDIR" "/S=0K" $0 $1 $2
- IntFmt $0 "0x%08X" $0
- WriteRegDWORD HKLM "${UNINST_KEY}" "EstimatedSize" "$0"
-[% END -%]
-
-SectionEnd
-
-[% IF system_install_mode -%]
-Section "Uninstall"
- RMDir /r "$INSTDIR"
- DeleteRegKey HKLM "${UNINST_KEY}"
- SetShellVarContext all
- Delete "$SMPROGRAMS\[% c('var/Project_Name') %].lnk"
- Delete "$DESKTOP\[% c('var/Project_Name') %].lnk"
-SectionEnd
-[% END -%]
-
-Function CreateShortcuts
-[% IF system_install_mode -%]
- SetShellVarContext all
-[% END -%]
- CreateShortCut "$SMPROGRAMS\[% c('var/Project_Name') %].lnk" "$INSTDIR\[% IF !system_install_mode -%]Browser\[% END -%][% c('var/exe_name') %].exe"
- CreateShortCut "$DESKTOP\[% c('var/Project_Name') %].lnk" "$INSTDIR\[% IF !system_install_mode -%]Browser\[% END -%][% c('var/exe_name') %].exe"
-
-FunctionEnd
-;--------------------------------
-;Installer Functions
-
-Function .onInit
-
- ${IfNot} ${AtLeastWin7}
- MessageBox MB_USERICON|MB_OK "[% c('var/Project_Name') %] requires at least Windows 7"
- SetErrorLevel 1
- Quit
- ${EndIf}
-
- ; Don't install on systems that don't support SSE2. The parameter value of
- ; 10 is for PF_XMMI64_INSTRUCTIONS_AVAILABLE which will check whether the
- ; SSE2 instruction set is available.
- System::Call "kernel32::IsProcessorFeaturePresent(i 10)i .R7"
-
- ${If} "$R7" == "0"
- MessageBox MB_OK|MB_ICONSTOP "Sorry, [% c('var/Project_Name') %] can't be installed. This version of [% c('var/Project_Name') %] requires a processor with SSE2 support."
- Abort
- ${EndIf}
-
- !insertmacro MUI_LANGDLL_DISPLAY
-
-FunctionEnd
-
-;--------------------------------
-;Helper Functions
-
-Function CheckIfTargetDirectoryExists
-${If} ${FileExists} "$INSTDIR\*.*"
- MessageBox MB_YESNO "The destination directory already exists. You can try to upgrade the [% c('var/Project_Name') %], but if you run into any problems, use a new directory instead. Continue?" IDYES NoAbort
- Abort
- NoAbort:
-${EndIf}
-FunctionEnd
-
-Function StartBrowser
-[% IF !system_install_mode -%]
- ExecShell "open" "$INSTDIR/Start [% c('var/Project_Name') %].lnk"
-[% ELSE -%]
- ExecShell "open" "$INSTDIR/[% c('var/exe_name') %].exe"
-[% END -%]
-FunctionEnd
+; NSIS Installer for Tor/Base/Mullvad Browser
+; Based on NSIS examples by Joost Verburg.
+; Originally adapted to Tor Browser by Moritz Bartl
+; https://github.com/moba/tbb-windows-installer
+; Released under the zlib/libpng license.
+
+;--------------------------------
+ !include "FileFunc.nsh"
+ !include "LogicLib.nsh"
+ !include "MUI2.nsh"
+ !include "WinVer.nsh"
+
+;--------------------------------
+; General
+ ; Location of Tor/Base/Mullvad Browser to put into installer
+ !define PROGRAM_SOURCE ".\[% c('var/Project_Name') %]\"
+
+[% IF c("var/channel") == "release";
+ SET display_name = c('var/Project_Name');
+ ELSIF c("var/testbuild");
+ SET display_name = c('var/Project_Name') _ " Testbuild";
+ ELSE;
+ SET display_name = c('var/Project_Name_Channel');
+ END
+-%]
+ Name "[% display_name %]"
+ OutFile "browser-install.exe"
+
+ ; Default installation folder
+ InstallDir "$DESKTOP\[% display_name %]"
+
+ ; Best (but slowest) compression
+ SetCompressor /SOLID lzma
+ SetCompressorDictSize 32
+
+ ; Do not require elevated privileges
+ RequestExecutionLevel user
+
+ ; Support HiDPI displays
+ ManifestDPIAware true
+
+;--------------------------------
+; Metadata
+ VIProductVersion "[% pc('firefox', 'var/browser_series') %].0.0"
+ VIAddVersionKey "ProductName" "[% display_name %]"
+ VIAddVersionKey "ProductVersion" "[% c('var/torbrowser_version') %]"
+ VIAddVersionKey "FileDescription" "[% display_name %] Portable Installer"
+ VIAddVersionKey "LegalCopyright" "© [% pc('firefox', 'var/copyright_year') %] [% IF c('var/mullvad-browser') %]Mullvad, Tor Browser and Mozilla Developers[% ELSE %]The Tor Project[% END %]"
+
+;--------------------------------
+; Interface Configuration
+ !define MUI_ICON "[% c('var/projectname') %][% IF !c('var/base-browser') %]-[% c('var/channel') %][% END %].ico"
+ !define MUI_ABORTWARNING
+
+;--------------------------------
+; Modern UI settings
+ !define MUI_FINISHPAGE_NOREBOOTSUPPORT ; Reboot not required
+ !define MUI_FINISHPAGE_RUN
+ !define MUI_FINISHPAGE_RUN_FUNCTION "StartBrowser"
+
+ ; Misuse the option to show the readme to create the shortcuts.
+ ; Less ugly than MUI_PAGE_COMPONENTS.
+ !define MUI_FINISHPAGE_SHOWREADME
+ !define MUI_FINISHPAGE_SHOWREADME_TEXT "&Add Start Menu && Desktop shortcuts"
+ !define MUI_FINISHPAGE_SHOWREADME_FUNCTION "CreateShortCuts"
+
+;--------------------------------
+; Pages
+ !define MUI_PAGE_CUSTOMFUNCTION_LEAVE CheckIfTargetDirectoryExists
+ !insertmacro MUI_PAGE_DIRECTORY
+ !insertmacro MUI_PAGE_INSTFILES
+ !insertmacro MUI_PAGE_FINISH
+
+;--------------------------------
+; Languages
+ !insertmacro MUI_LANGUAGE "English" ; First language is the default language
+ !insertmacro MUI_LANGUAGE "Arabic" ; ar
+ !insertmacro MUI_LANGUAGE "Catalan" ; ca
+ !insertmacro MUI_LANGUAGE "Czech" ; cs
+ !insertmacro MUI_LANGUAGE "Danish" ; da
+ !insertmacro MUI_LANGUAGE "German" ; de
+ !insertmacro MUI_LANGUAGE "Greek" ; el
+ !insertmacro MUI_LANGUAGE "Spanish" ; es-ES
+ !insertmacro MUI_LANGUAGE "Farsi" ; fa
+ !insertmacro MUI_LANGUAGE "Finnish" ; fi
+ !insertmacro MUI_LANGUAGE "French" ; fr
+ !insertmacro MUI_LANGUAGE "ScotsGaelic" ; ga-IE
+ !insertmacro MUI_LANGUAGE "Hebrew" ; he
+ !insertmacro MUI_LANGUAGE "Hungarian" ; hu
+ !insertmacro MUI_LANGUAGE "Indonesian"; id
+ !insertmacro MUI_LANGUAGE "Icelandic" ; is
+ !insertmacro MUI_LANGUAGE "Italian" ; it
+ !insertmacro MUI_LANGUAGE "Japanese" ; ja
+ !insertmacro MUI_LANGUAGE "Georgian" ; ka
+ !insertmacro MUI_LANGUAGE "Korean" ; ko
+ !insertmacro MUI_LANGUAGE "Lithuanian" ; lt
+ !insertmacro MUI_LANGUAGE "Macedonian" ; mk
+ !insertmacro MUI_LANGUAGE "Malay" ; ms
+ ; Burmese - my: not available on NSIS
+ !insertmacro MUI_LANGUAGE "Norwegian" ; nb-NO
+ !insertmacro MUI_LANGUAGE "Dutch" ; nl
+ !insertmacro MUI_LANGUAGE "Polish" ; pl
+ !insertmacro MUI_LANGUAGE "PortugueseBR" ; pt-BR
+ !insertmacro MUI_LANGUAGE "Romanian" ; ro
+ !insertmacro MUI_LANGUAGE "Russian" ; ru
+ !insertmacro MUI_LANGUAGE "Albanian" ; sq
+ !insertmacro MUI_LANGUAGE "Swedish" ; sv-SE
+ !insertmacro MUI_LANGUAGE "Thai" ; th
+ !insertmacro MUI_LANGUAGE "Turkish" ; tr
+ !insertmacro MUI_LANGUAGE "Ukrainian" ; uk
+ !insertmacro MUI_LANGUAGE "Vietnamese" ; vi
+ !insertmacro MUI_LANGUAGE "SimpChinese" ; zh-hans, zh-cn
+ !insertmacro MUI_LANGUAGE "TradChinese" ; zh-hant, zh-tw
+
+;--------------------------------
+; Reserve Files
+
+ ; If you are using solid compression, files that are required before
+ ; the actual installation should be stored first in the data block,
+ ; because this will make your installer start faster.
+
+ !insertmacro MUI_RESERVEFILE_LANGDLL
+
+;--------------------------------
+; Installer Sections
+
+Section "Browser" SecBrowser
+ SetOutPath "$INSTDIR"
+ File /r "${PROGRAM_SOURCE}\*.*"
+ CreateShortCut "$INSTDIR\[% display_name %].lnk" "$INSTDIR\Browser\[% c('var/exe_name') %].exe"
+SectionEnd
+
+;--------------------------------
+; Installer Functions
+
+Function .onInit
+ ${IfNot} ${AtLeastWin7}
+ MessageBox MB_USERICON|MB_OK "[% c('var/Project_Name') %] requires at least Windows 7"
+ SetErrorLevel 1
+ Quit
+ ${EndIf}
+
+ ; Don't install on systems that don't support SSE2. The parameter value of
+ ; 10 is for PF_XMMI64_INSTRUCTIONS_AVAILABLE which will check whether the
+ ; SSE2 instruction set is available.
+ System::Call "kernel32::IsProcessorFeaturePresent(i 10)i .R7"
+ ${If} "$R7" == "0"
+ MessageBox MB_OK|MB_ICONSTOP "Sorry, [% c('var/Project_Name') %] can't be installed. This version of [% c('var/Project_Name') %] requires a processor with SSE2 support."
+ Abort
+ ${EndIf}
+
+ !insertmacro MUI_LANGDLL_DISPLAY
+FunctionEnd
+
+Function CheckIfTargetDirectoryExists
+ ${If} ${FileExists} "$INSTDIR\*.*"
+ MessageBox MB_YESNO "The destination directory already exists. Do you want to continue anyway?" IDYES +2
+ Abort
+ ${EndIf}
+FunctionEnd
+
+Function CreateShortcuts
+ CreateShortCut "$SMPROGRAMS\[% display_name %].lnk" "$INSTDIR\[% IF !system_install_mode -%]Browser\[% END -%][% c('var/exe_name') %].exe"
+ CreateShortCut "$DESKTOP\[% display_name %].lnk" "$INSTDIR\[% IF !system_install_mode -%]Browser\[% END -%][% c('var/exe_name') %].exe"
+FunctionEnd
+
+Function StartBrowser
+ ExecShell "open" "$INSTDIR/[% display_name %].lnk"
+FunctionEnd
View it on GitLab: https://gitlab.torproject.org/tpo/applications/tor-browser-build/-/commit/1…
--
View it on GitLab: https://gitlab.torproject.org/tpo/applications/tor-browser-build/-/commit/1…
You're receiving this email because of your account on gitlab.torproject.org.
[View Less]
1
0

[Git][tpo/applications/mullvad-browser][mullvad-browser-115.7.0esr-13.5-1] fixup! Bug 32308: use direct browser sizing for letterboxing.
by ma1 (@ma1) 29 Jan '24
by ma1 (@ma1) 29 Jan '24
29 Jan '24
ma1 pushed to branch mullvad-browser-115.7.0esr-13.5-1 at The Tor Project / Applications / Mullvad Browser
Commits:
c55896fb by hackademix at 2024-01-29T16:33:56+01:00
fixup! Bug 32308: use direct browser sizing for letterboxing.
Bug 41917: Make the appearance of letterboxing look more intentional
- - - - -
3 changed files:
- browser/app/profile/001-base-profile.js
- browser/base/content/browser.css
- toolkit/components/resistfingerprinting/RFPHelper.sys.mjs
Changes:
==================…
[View More]===================
browser/app/profile/001-base-profile.js
=====================================
@@ -375,6 +375,10 @@ pref("security.remote_settings.intermediates.enabled", false);
pref("dom.use_components_shim", false);
// Enable letterboxing
pref("privacy.resistFingerprinting.letterboxing", true);
+// tor-browser#41917 center letterboxed area vertically
+pref("privacy.resistFingerprinting.letterboxing.vcenter", true);
+// tor-browser#41917 letterboxing gradient background
+pref("privacy.resistFingerprinting.letterboxing.gradient", true);
// tor-browser#41695: how many warnings we show if user closes them without restoring the window size
pref("privacy.resistFingerprinting.resizeWarnings", 3);
// tor-browser#33282: new windows start at 1400x900 when there's enough screen space, otherwise down by 200x100 blocks
=====================================
browser/base/content/browser.css
=====================================
@@ -134,6 +134,56 @@ body {
doesn't get notified on horizontal shrinking.
*/
overflow-x: hidden;
+ background: var(--letterboxing-bgcolor);
+}
+
+.letterboxing {
+ --letterboxing-border-radius: 8px;
+ --letterboxing-border-top-radius: 0;
+ --letterboxing-vertical-alignment: start;
+ --letterboxing-shadow-color: rgba(12, 12, 13, 0.10);
+ --letterboxing-bgcolor: var(--tabpanel-background-color);
+ --letterboxing-gradient-color1: var(--letterboxing-bgcolor);
+ --letterboxing-gradient-color2: color-mix(in srgb, var(--chrome-content-separator-color) 50%, var(--letterboxing-bgcolor));
+}
+
+.letterboxing.letterboxing-vcenter .browserContainer:not(.responsive-mode) > .browserStack:not(.exclude-letterboxing) {
+ --letterboxing-border-top-radius: var(--letterboxing-border-radius);
+ --letterboxing-vertical-alignment: center;
+}
+
+.letterboxing.letterboxing-gradient .browserContainer {
+ background: linear-gradient(283deg, var(--letterboxing-gradient-color1) 0%, var(--letterboxing-gradient-color2) 100%), var(--letterboxing-bgcolor);
+ box-shadow: rgba(0, 0, 0, 0.5) 0px -1px 2px;
+}
+
+/*
+ Align status bar with content.
+ TODO: switch to nested CSS selectors for conciseness when available (Firefox >= 117)
+*/
+.letterboxing .browserContainer:not(.responsive-mode) > .browserStack:not(.exclude-letterboxing)
+ > #statuspanel:not([hidden]) {
+ position: relative;
+ place-self: end left;
+ left: 0;
+ right: 0;
+ --letterboxing-status-left-radius: var(--letterboxing-border-radius);
+ --letterboxing-status-right-radius: 0;
+}
+.letterboxing .browserContainer:not(.responsive-mode) > .browserStack:not(.exclude-letterboxing)
+ > #statuspanel:not([mirror]):-moz-locale-dir(rtl),
+.letterboxing .browserContainer:not(.responsive-mode) > .browserStack:not(.exclude-letterboxing)
+ > #statuspanel[mirror]:-moz-locale-dir(ltr) {
+ left: 0;
+ right: 0;
+ --letterboxing-status-right-radius: var(--letterboxing-border-radius);
+ --letterboxing-status-left-radius: 0;
+ justify-self: right;
+}
+
+.letterboxing .browserContainer:not(.responsive-mode) > .browserStack:not(.exclude-letterboxing)
+#statuspanel-label {
+ border-radius: 0 0 var(--letterboxing-status-right-radius) var(--letterboxing-status-left-radius);
}
/**
@@ -142,21 +192,15 @@ body {
**/
.letterboxing .browserContainer:not(.responsive-mode) > .browserStack:not(.exclude-letterboxing) > browser {
/* width & height to be dynamically set by RFPHelper.jsm */
- outline: 1px solid var(--chrome-content-separator-color);
+ box-shadow: 0px 4px 8px 0px var(--letterboxing-shadow-color);
+ border-radius: var(--letterboxing-border-radius);
+ border-top-left-radius: var(--letterboxing-border-top-radius);
+ border-top-right-radius: var(--letterboxing-border-top-radius);
}
-.exclude-letterboxing > browser {
- outline: initial;
-}
-
-:root:not([inDOMFullscreen]) .letterboxing.letterboxing-ready .browserContainer:not(.responsive-mode) > .browserStack:not(.exclude-letterboxing) {
- place-content: start center;
-}
-
-/* extend down the toolbar's colors when letterboxing is enabled */
-.letterboxing {
- background-color: var(--toolbar-bgcolor);
- background-image: var(--toolbar-bgimage);
+:root:not([inDOMFullscreen]) .letterboxing.letterboxing-ready .browserContainer:not(.responsive-mode)
+ > .browserStack:not(.exclude-letterboxing) {
+ place-content: var(--letterboxing-vertical-alignment) center;
}
#toolbar-menubar[autohide="true"] {
=====================================
toolkit/components/resistfingerprinting/RFPHelper.sys.mjs
=====================================
@@ -14,6 +14,11 @@ const kPrefLetterboxingDimensions =
"privacy.resistFingerprinting.letterboxing.dimensions";
const kPrefLetterboxingTesting =
"privacy.resistFingerprinting.letterboxing.testing";
+const kPrefLetterboxingVcenter =
+ "privacy.resistFingerprinting.letterboxing.vcenter";
+const kPrefLetterboxingGradient =
+ "privacy.resistFingerprinting.letterboxing.gradient";
+
const kTopicDOMWindowOpened = "domwindowopened";
const kPrefResizeWarnings = "privacy.resistFingerprinting.resizeWarnings";
@@ -140,6 +145,9 @@ class _RFPHelper {
// Add unconditional observers
Services.prefs.addObserver(kPrefResistFingerprinting, this);
Services.prefs.addObserver(kPrefLetterboxing, this);
+ Services.prefs.addObserver(kPrefLetterboxingVcenter, this);
+ Services.prefs.addObserver(kPrefLetterboxingGradient, this);
+
XPCOMUtils.defineLazyPreferenceGetter(
this,
"_letterboxingDimensions",
@@ -171,6 +179,8 @@ class _RFPHelper {
// Remove unconditional observers
Services.prefs.removeObserver(kPrefResistFingerprinting, this);
+ Services.prefs.removeObserver(kPrefLetterboxingGradient, this);
+ Services.prefs.removeObserver(kPrefLetterboxingVcenter, this);
Services.prefs.removeObserver(kPrefLetterboxing, this);
// Remove the RFP observers, swallowing exceptions if they weren't present
this._removeRFPObservers();
@@ -218,6 +228,8 @@ class _RFPHelper {
this._handleSpoofEnglishChanged();
break;
case kPrefLetterboxing:
+ case kPrefLetterboxingVcenter:
+ case kPrefLetterboxingGradient:
this._handleLetterboxingPrefChanged();
break;
default:
@@ -429,8 +441,7 @@ class _RFPHelper {
});
}
- getLetterboxingDefaultRule(aBrowser) {
- let document = aBrowser.ownerDocument;
+ getLetterboxingDefaultRule(document) {
return (document._letterBoxingSizingRule ||= (() => {
// If not already cached on the document object, traverse the CSSOM and
// find the rule applying the default letterboxing styles to browsers
@@ -555,11 +566,16 @@ class _RFPHelper {
return;
}
+ let lastRoundedSize;
+
const roundDimensions = (aWidth, aHeight) => {
- const r = (aWidth, aHeight) => ({
- width: `var(--rdm-width, ${aWidth}px)`,
- height: `var(--rdm-height, ${aHeight}px)`,
- });
+ const r = (width, height) => {
+ lastRoundedSize = {width, height};
+ return {
+ width: `var(--rdm-width, ${width}px)`,
+ height: `var(--rdm-height, ${height}px)`,
+ }
+ };
let result;
@@ -642,7 +658,7 @@ class _RFPHelper {
const roundedDefault = roundDimensions(containerWidth, containerHeight);
styleChanges.queueIfNeeded(
- this.getLetterboxingDefaultRule(aBrowser),
+ this.getLetterboxingDefaultRule(aBrowser.ownerDocument),
roundedDefault
);
@@ -655,6 +671,21 @@ class _RFPHelper {
: { width: "", height: "" }; // otherwise we can keep the default (rounded) size
styleChanges.queueIfNeeded(aBrowser, roundedInline);
+ if (lastRoundedSize) {
+ // check wether the letterboxing margin is less than the border radius, and if so flatten the borders
+ let borderRadius = parseInt(win.getComputedStyle(browserContainer).getPropertyValue("--letterboxing-border-radius"));
+ if (borderRadius &&
+ (parentWidth - lastRoundedSize.width < borderRadius &&
+ parentHeight - lastRoundedSize.height < borderRadius)) {
+ borderRadius = 0;
+ } else {
+ borderRadius = "";
+ }
+ styleChanges.queueIfNeeded(browserParent, {
+ '--letterboxing-border-radius': borderRadius
+ });
+ }
+
// If the size of the content is already quantized, we do nothing.
if (!styleChanges.length) {
log(`${logPrefix} is_rounded == true`);
@@ -690,6 +721,10 @@ class _RFPHelper {
_updateSizeForTabsInWindow(aWindow) {
let tabBrowser = aWindow.gBrowser;
tabBrowser.tabpanels?.classList.add("letterboxing");
+ tabBrowser.tabpanels?.classList.toggle("letterboxing-vcenter",
+ Services.prefs.getBoolPref(kPrefLetterboxingVcenter, false));
+ tabBrowser.tabpanels?.classList.toggle("letterboxing-gradient",
+ Services.prefs.getBoolPref(kPrefLetterboxingGradient, false));
for (let tab of tabBrowser.tabs) {
let browser = tab.linkedBrowser;
View it on GitLab: https://gitlab.torproject.org/tpo/applications/mullvad-browser/-/commit/c55…
--
View it on GitLab: https://gitlab.torproject.org/tpo/applications/mullvad-browser/-/commit/c55…
You're receiving this email because of your account on gitlab.torproject.org.
[View Less]
1
0

[Git][tpo/applications/tor-browser][base-browser-115.7.0esr-13.5-1] fixup! Bug 32308: use direct browser sizing for letterboxing.
by ma1 (@ma1) 29 Jan '24
by ma1 (@ma1) 29 Jan '24
29 Jan '24
ma1 pushed to branch base-browser-115.7.0esr-13.5-1 at The Tor Project / Applications / Tor Browser
Commits:
0cb13087 by hackademix at 2024-01-29T16:32:32+01:00
fixup! Bug 32308: use direct browser sizing for letterboxing.
Bug 41917: Make the appearance of letterboxing look more intentional
- - - - -
3 changed files:
- browser/app/profile/001-base-profile.js
- browser/base/content/browser.css
- toolkit/components/resistfingerprinting/RFPHelper.sys.mjs
Changes:
=========================…
[View More]============
browser/app/profile/001-base-profile.js
=====================================
@@ -376,6 +376,10 @@ pref("security.remote_settings.intermediates.enabled", false);
pref("dom.use_components_shim", false);
// Enable letterboxing
pref("privacy.resistFingerprinting.letterboxing", true);
+// tor-browser#41917 center letterboxed area vertically
+pref("privacy.resistFingerprinting.letterboxing.vcenter", true);
+// tor-browser#41917 letterboxing gradient background
+pref("privacy.resistFingerprinting.letterboxing.gradient", true);
// tor-browser#41695: how many warnings we show if user closes them without restoring the window size
pref("privacy.resistFingerprinting.resizeWarnings", 3);
// tor-browser#33282: new windows start at 1400x900 when there's enough screen space, otherwise down by 200x100 blocks
=====================================
browser/base/content/browser.css
=====================================
@@ -134,6 +134,56 @@ body {
doesn't get notified on horizontal shrinking.
*/
overflow-x: hidden;
+ background: var(--letterboxing-bgcolor);
+}
+
+.letterboxing {
+ --letterboxing-border-radius: 8px;
+ --letterboxing-border-top-radius: 0;
+ --letterboxing-vertical-alignment: start;
+ --letterboxing-shadow-color: rgba(12, 12, 13, 0.10);
+ --letterboxing-bgcolor: var(--tabpanel-background-color);
+ --letterboxing-gradient-color1: var(--letterboxing-bgcolor);
+ --letterboxing-gradient-color2: color-mix(in srgb, var(--chrome-content-separator-color) 50%, var(--letterboxing-bgcolor));
+}
+
+.letterboxing.letterboxing-vcenter .browserContainer:not(.responsive-mode) > .browserStack:not(.exclude-letterboxing) {
+ --letterboxing-border-top-radius: var(--letterboxing-border-radius);
+ --letterboxing-vertical-alignment: center;
+}
+
+.letterboxing.letterboxing-gradient .browserContainer {
+ background: linear-gradient(283deg, var(--letterboxing-gradient-color1) 0%, var(--letterboxing-gradient-color2) 100%), var(--letterboxing-bgcolor);
+ box-shadow: rgba(0, 0, 0, 0.5) 0px -1px 2px;
+}
+
+/*
+ Align status bar with content.
+ TODO: switch to nested CSS selectors for conciseness when available (Firefox >= 117)
+*/
+.letterboxing .browserContainer:not(.responsive-mode) > .browserStack:not(.exclude-letterboxing)
+ > #statuspanel:not([hidden]) {
+ position: relative;
+ place-self: end left;
+ left: 0;
+ right: 0;
+ --letterboxing-status-left-radius: var(--letterboxing-border-radius);
+ --letterboxing-status-right-radius: 0;
+}
+.letterboxing .browserContainer:not(.responsive-mode) > .browserStack:not(.exclude-letterboxing)
+ > #statuspanel:not([mirror]):-moz-locale-dir(rtl),
+.letterboxing .browserContainer:not(.responsive-mode) > .browserStack:not(.exclude-letterboxing)
+ > #statuspanel[mirror]:-moz-locale-dir(ltr) {
+ left: 0;
+ right: 0;
+ --letterboxing-status-right-radius: var(--letterboxing-border-radius);
+ --letterboxing-status-left-radius: 0;
+ justify-self: right;
+}
+
+.letterboxing .browserContainer:not(.responsive-mode) > .browserStack:not(.exclude-letterboxing)
+#statuspanel-label {
+ border-radius: 0 0 var(--letterboxing-status-right-radius) var(--letterboxing-status-left-radius);
}
/**
@@ -142,21 +192,15 @@ body {
**/
.letterboxing .browserContainer:not(.responsive-mode) > .browserStack:not(.exclude-letterboxing) > browser {
/* width & height to be dynamically set by RFPHelper.jsm */
- outline: 1px solid var(--chrome-content-separator-color);
+ box-shadow: 0px 4px 8px 0px var(--letterboxing-shadow-color);
+ border-radius: var(--letterboxing-border-radius);
+ border-top-left-radius: var(--letterboxing-border-top-radius);
+ border-top-right-radius: var(--letterboxing-border-top-radius);
}
-.exclude-letterboxing > browser {
- outline: initial;
-}
-
-:root:not([inDOMFullscreen]) .letterboxing.letterboxing-ready .browserContainer:not(.responsive-mode) > .browserStack:not(.exclude-letterboxing) {
- place-content: start center;
-}
-
-/* extend down the toolbar's colors when letterboxing is enabled */
-.letterboxing {
- background-color: var(--toolbar-bgcolor);
- background-image: var(--toolbar-bgimage);
+:root:not([inDOMFullscreen]) .letterboxing.letterboxing-ready .browserContainer:not(.responsive-mode)
+ > .browserStack:not(.exclude-letterboxing) {
+ place-content: var(--letterboxing-vertical-alignment) center;
}
#toolbar-menubar[autohide="true"] {
=====================================
toolkit/components/resistfingerprinting/RFPHelper.sys.mjs
=====================================
@@ -14,6 +14,11 @@ const kPrefLetterboxingDimensions =
"privacy.resistFingerprinting.letterboxing.dimensions";
const kPrefLetterboxingTesting =
"privacy.resistFingerprinting.letterboxing.testing";
+const kPrefLetterboxingVcenter =
+ "privacy.resistFingerprinting.letterboxing.vcenter";
+const kPrefLetterboxingGradient =
+ "privacy.resistFingerprinting.letterboxing.gradient";
+
const kTopicDOMWindowOpened = "domwindowopened";
const kPrefResizeWarnings = "privacy.resistFingerprinting.resizeWarnings";
@@ -140,6 +145,9 @@ class _RFPHelper {
// Add unconditional observers
Services.prefs.addObserver(kPrefResistFingerprinting, this);
Services.prefs.addObserver(kPrefLetterboxing, this);
+ Services.prefs.addObserver(kPrefLetterboxingVcenter, this);
+ Services.prefs.addObserver(kPrefLetterboxingGradient, this);
+
XPCOMUtils.defineLazyPreferenceGetter(
this,
"_letterboxingDimensions",
@@ -171,6 +179,8 @@ class _RFPHelper {
// Remove unconditional observers
Services.prefs.removeObserver(kPrefResistFingerprinting, this);
+ Services.prefs.removeObserver(kPrefLetterboxingGradient, this);
+ Services.prefs.removeObserver(kPrefLetterboxingVcenter, this);
Services.prefs.removeObserver(kPrefLetterboxing, this);
// Remove the RFP observers, swallowing exceptions if they weren't present
this._removeRFPObservers();
@@ -218,6 +228,8 @@ class _RFPHelper {
this._handleSpoofEnglishChanged();
break;
case kPrefLetterboxing:
+ case kPrefLetterboxingVcenter:
+ case kPrefLetterboxingGradient:
this._handleLetterboxingPrefChanged();
break;
default:
@@ -429,8 +441,7 @@ class _RFPHelper {
});
}
- getLetterboxingDefaultRule(aBrowser) {
- let document = aBrowser.ownerDocument;
+ getLetterboxingDefaultRule(document) {
return (document._letterBoxingSizingRule ||= (() => {
// If not already cached on the document object, traverse the CSSOM and
// find the rule applying the default letterboxing styles to browsers
@@ -555,11 +566,16 @@ class _RFPHelper {
return;
}
+ let lastRoundedSize;
+
const roundDimensions = (aWidth, aHeight) => {
- const r = (aWidth, aHeight) => ({
- width: `var(--rdm-width, ${aWidth}px)`,
- height: `var(--rdm-height, ${aHeight}px)`,
- });
+ const r = (width, height) => {
+ lastRoundedSize = {width, height};
+ return {
+ width: `var(--rdm-width, ${width}px)`,
+ height: `var(--rdm-height, ${height}px)`,
+ }
+ };
let result;
@@ -642,7 +658,7 @@ class _RFPHelper {
const roundedDefault = roundDimensions(containerWidth, containerHeight);
styleChanges.queueIfNeeded(
- this.getLetterboxingDefaultRule(aBrowser),
+ this.getLetterboxingDefaultRule(aBrowser.ownerDocument),
roundedDefault
);
@@ -655,6 +671,21 @@ class _RFPHelper {
: { width: "", height: "" }; // otherwise we can keep the default (rounded) size
styleChanges.queueIfNeeded(aBrowser, roundedInline);
+ if (lastRoundedSize) {
+ // check wether the letterboxing margin is less than the border radius, and if so flatten the borders
+ let borderRadius = parseInt(win.getComputedStyle(browserContainer).getPropertyValue("--letterboxing-border-radius"));
+ if (borderRadius &&
+ (parentWidth - lastRoundedSize.width < borderRadius &&
+ parentHeight - lastRoundedSize.height < borderRadius)) {
+ borderRadius = 0;
+ } else {
+ borderRadius = "";
+ }
+ styleChanges.queueIfNeeded(browserParent, {
+ '--letterboxing-border-radius': borderRadius
+ });
+ }
+
// If the size of the content is already quantized, we do nothing.
if (!styleChanges.length) {
log(`${logPrefix} is_rounded == true`);
@@ -690,6 +721,10 @@ class _RFPHelper {
_updateSizeForTabsInWindow(aWindow) {
let tabBrowser = aWindow.gBrowser;
tabBrowser.tabpanels?.classList.add("letterboxing");
+ tabBrowser.tabpanels?.classList.toggle("letterboxing-vcenter",
+ Services.prefs.getBoolPref(kPrefLetterboxingVcenter, false));
+ tabBrowser.tabpanels?.classList.toggle("letterboxing-gradient",
+ Services.prefs.getBoolPref(kPrefLetterboxingGradient, false));
for (let tab of tabBrowser.tabs) {
let browser = tab.linkedBrowser;
View it on GitLab: https://gitlab.torproject.org/tpo/applications/tor-browser/-/commit/0cb1308…
--
View it on GitLab: https://gitlab.torproject.org/tpo/applications/tor-browser/-/commit/0cb1308…
You're receiving this email because of your account on gitlab.torproject.org.
[View Less]
1
0

[Git][tpo/applications/tor-browser][tor-browser-115.7.0esr-13.5-1] 2 commits: fixup! Bug 32308: use direct browser sizing for letterboxing.
by ma1 (@ma1) 29 Jan '24
by ma1 (@ma1) 29 Jan '24
29 Jan '24
ma1 pushed to branch tor-browser-115.7.0esr-13.5-1 at The Tor Project / Applications / Tor Browser
Commits:
8d25c1cc by hackademix at 2024-01-29T16:28:12+01:00
fixup! Bug 32308: use direct browser sizing for letterboxing.
Bug 41917: Make the appearance of letterboxing look more intentional
- - - - -
366c81df by hackademix at 2024-01-29T16:28:18+01:00
Bug 41917: Tor brand-specific styles.
- - - - -
6 changed files:
- browser/app/profile/001-base-profile.js
- browser/base/content/browser.…
[View More]css
- browser/themes/shared/browser-shared.css
- browser/themes/shared/jar.inc.mn
- + browser/themes/shared/tor-branding.css
- toolkit/components/resistfingerprinting/RFPHelper.sys.mjs
Changes:
=====================================
browser/app/profile/001-base-profile.js
=====================================
@@ -376,6 +376,10 @@ pref("security.remote_settings.intermediates.enabled", false);
pref("dom.use_components_shim", false);
// Enable letterboxing
pref("privacy.resistFingerprinting.letterboxing", true);
+// tor-browser#41917 center letterboxed area vertically
+pref("privacy.resistFingerprinting.letterboxing.vcenter", true);
+// tor-browser#41917 letterboxing gradient background
+pref("privacy.resistFingerprinting.letterboxing.gradient", true);
// tor-browser#41695: how many warnings we show if user closes them without restoring the window size
pref("privacy.resistFingerprinting.resizeWarnings", 3);
// tor-browser#33282: new windows start at 1400x900 when there's enough screen space, otherwise down by 200x100 blocks
=====================================
browser/base/content/browser.css
=====================================
@@ -134,6 +134,56 @@ body {
doesn't get notified on horizontal shrinking.
*/
overflow-x: hidden;
+ background: var(--letterboxing-bgcolor);
+}
+
+.letterboxing {
+ --letterboxing-border-radius: 8px;
+ --letterboxing-border-top-radius: 0;
+ --letterboxing-vertical-alignment: start;
+ --letterboxing-shadow-color: rgba(12, 12, 13, 0.10);
+ --letterboxing-bgcolor: var(--tabpanel-background-color);
+ --letterboxing-gradient-color1: var(--letterboxing-bgcolor);
+ --letterboxing-gradient-color2: color-mix(in srgb, var(--chrome-content-separator-color) 50%, var(--letterboxing-bgcolor));
+}
+
+.letterboxing.letterboxing-vcenter .browserContainer:not(.responsive-mode) > .browserStack:not(.exclude-letterboxing) {
+ --letterboxing-border-top-radius: var(--letterboxing-border-radius);
+ --letterboxing-vertical-alignment: center;
+}
+
+.letterboxing.letterboxing-gradient .browserContainer {
+ background: linear-gradient(283deg, var(--letterboxing-gradient-color1) 0%, var(--letterboxing-gradient-color2) 100%), var(--letterboxing-bgcolor);
+ box-shadow: rgba(0, 0, 0, 0.5) 0px -1px 2px;
+}
+
+/*
+ Align status bar with content.
+ TODO: switch to nested CSS selectors for conciseness when available (Firefox >= 117)
+*/
+.letterboxing .browserContainer:not(.responsive-mode) > .browserStack:not(.exclude-letterboxing)
+ > #statuspanel:not([hidden]) {
+ position: relative;
+ place-self: end left;
+ left: 0;
+ right: 0;
+ --letterboxing-status-left-radius: var(--letterboxing-border-radius);
+ --letterboxing-status-right-radius: 0;
+}
+.letterboxing .browserContainer:not(.responsive-mode) > .browserStack:not(.exclude-letterboxing)
+ > #statuspanel:not([mirror]):-moz-locale-dir(rtl),
+.letterboxing .browserContainer:not(.responsive-mode) > .browserStack:not(.exclude-letterboxing)
+ > #statuspanel[mirror]:-moz-locale-dir(ltr) {
+ left: 0;
+ right: 0;
+ --letterboxing-status-right-radius: var(--letterboxing-border-radius);
+ --letterboxing-status-left-radius: 0;
+ justify-self: right;
+}
+
+.letterboxing .browserContainer:not(.responsive-mode) > .browserStack:not(.exclude-letterboxing)
+#statuspanel-label {
+ border-radius: 0 0 var(--letterboxing-status-right-radius) var(--letterboxing-status-left-radius);
}
/**
@@ -142,21 +192,15 @@ body {
**/
.letterboxing .browserContainer:not(.responsive-mode) > .browserStack:not(.exclude-letterboxing) > browser {
/* width & height to be dynamically set by RFPHelper.jsm */
- outline: 1px solid var(--chrome-content-separator-color);
+ box-shadow: 0px 4px 8px 0px var(--letterboxing-shadow-color);
+ border-radius: var(--letterboxing-border-radius);
+ border-top-left-radius: var(--letterboxing-border-top-radius);
+ border-top-right-radius: var(--letterboxing-border-top-radius);
}
-.exclude-letterboxing > browser {
- outline: initial;
-}
-
-:root:not([inDOMFullscreen]) .letterboxing.letterboxing-ready .browserContainer:not(.responsive-mode) > .browserStack:not(.exclude-letterboxing) {
- place-content: start center;
-}
-
-/* extend down the toolbar's colors when letterboxing is enabled */
-.letterboxing {
- background-color: var(--toolbar-bgcolor);
- background-image: var(--toolbar-bgimage);
+:root:not([inDOMFullscreen]) .letterboxing.letterboxing-ready .browserContainer:not(.responsive-mode)
+ > .browserStack:not(.exclude-letterboxing) {
+ place-content: var(--letterboxing-vertical-alignment) center;
}
#toolbar-menubar[autohide="true"] {
=====================================
browser/themes/shared/browser-shared.css
=====================================
@@ -24,6 +24,7 @@
@import url("chrome://browser/skin/UITour.css");
@import url("chrome://global/skin/browser-colors.css");
@import url("chrome://browser/skin/tor-urlbar-button.css");
+@import url("chrome://browser/skin/tor-branding.css");
@import url("chrome://browser/skin/onionlocation.css");
@namespace html url("http://www.w3.org/1999/xhtml");
=====================================
browser/themes/shared/jar.inc.mn
=====================================
@@ -29,6 +29,7 @@
skin/classic/browser/tabs.css (../shared/tabs.css)
skin/classic/browser/toolbarbuttons.css (../shared/toolbarbuttons.css)
skin/classic/browser/toolbarbutton-icons.css (../shared/toolbarbutton-icons.css)
+ skin/classic/browser/tor-branding.css (../shared/tor-branding.css)
skin/classic/browser/tor-urlbar-button.css (../shared/tor-urlbar-button.css)
skin/classic/browser/urlbar-dynamic-results.css (../shared/urlbar-dynamic-results.css)
skin/classic/browser/urlbar-searchbar.css (../shared/urlbar-searchbar.css)
=====================================
browser/themes/shared/tor-branding.css
=====================================
@@ -0,0 +1,13 @@
+.letterboxing {
+ --letterboxing-bgcolor: var(--color-grey-light-20, #F0F0F4);
+ --letterboxing-gradient-color1: rgba(0, 219, 222, 0.02);
+ --letterboxing-gradient-color2: rgba(252, 0, 255, 0.02);
+}
+
+@media (prefers-color-scheme: dark) {
+ .letterboxing {
+ --letterboxing-bgcolor: var(--color-grey-dark-10, #52525E);
+ --letterboxing-gradient-color1: rgba(0, 219, 222, 0.06);
+ --letterboxing-gradient-color2: rgba(252, 0, 255, 0.06);
+ }
+}
\ No newline at end of file
=====================================
toolkit/components/resistfingerprinting/RFPHelper.sys.mjs
=====================================
@@ -14,6 +14,11 @@ const kPrefLetterboxingDimensions =
"privacy.resistFingerprinting.letterboxing.dimensions";
const kPrefLetterboxingTesting =
"privacy.resistFingerprinting.letterboxing.testing";
+const kPrefLetterboxingVcenter =
+ "privacy.resistFingerprinting.letterboxing.vcenter";
+const kPrefLetterboxingGradient =
+ "privacy.resistFingerprinting.letterboxing.gradient";
+
const kTopicDOMWindowOpened = "domwindowopened";
const kPrefResizeWarnings = "privacy.resistFingerprinting.resizeWarnings";
@@ -140,6 +145,9 @@ class _RFPHelper {
// Add unconditional observers
Services.prefs.addObserver(kPrefResistFingerprinting, this);
Services.prefs.addObserver(kPrefLetterboxing, this);
+ Services.prefs.addObserver(kPrefLetterboxingVcenter, this);
+ Services.prefs.addObserver(kPrefLetterboxingGradient, this);
+
XPCOMUtils.defineLazyPreferenceGetter(
this,
"_letterboxingDimensions",
@@ -171,6 +179,8 @@ class _RFPHelper {
// Remove unconditional observers
Services.prefs.removeObserver(kPrefResistFingerprinting, this);
+ Services.prefs.removeObserver(kPrefLetterboxingGradient, this);
+ Services.prefs.removeObserver(kPrefLetterboxingVcenter, this);
Services.prefs.removeObserver(kPrefLetterboxing, this);
// Remove the RFP observers, swallowing exceptions if they weren't present
this._removeRFPObservers();
@@ -218,6 +228,8 @@ class _RFPHelper {
this._handleSpoofEnglishChanged();
break;
case kPrefLetterboxing:
+ case kPrefLetterboxingVcenter:
+ case kPrefLetterboxingGradient:
this._handleLetterboxingPrefChanged();
break;
default:
@@ -429,8 +441,7 @@ class _RFPHelper {
});
}
- getLetterboxingDefaultRule(aBrowser) {
- let document = aBrowser.ownerDocument;
+ getLetterboxingDefaultRule(document) {
return (document._letterBoxingSizingRule ||= (() => {
// If not already cached on the document object, traverse the CSSOM and
// find the rule applying the default letterboxing styles to browsers
@@ -555,11 +566,16 @@ class _RFPHelper {
return;
}
+ let lastRoundedSize;
+
const roundDimensions = (aWidth, aHeight) => {
- const r = (aWidth, aHeight) => ({
- width: `var(--rdm-width, ${aWidth}px)`,
- height: `var(--rdm-height, ${aHeight}px)`,
- });
+ const r = (width, height) => {
+ lastRoundedSize = {width, height};
+ return {
+ width: `var(--rdm-width, ${width}px)`,
+ height: `var(--rdm-height, ${height}px)`,
+ }
+ };
let result;
@@ -642,7 +658,7 @@ class _RFPHelper {
const roundedDefault = roundDimensions(containerWidth, containerHeight);
styleChanges.queueIfNeeded(
- this.getLetterboxingDefaultRule(aBrowser),
+ this.getLetterboxingDefaultRule(aBrowser.ownerDocument),
roundedDefault
);
@@ -655,6 +671,21 @@ class _RFPHelper {
: { width: "", height: "" }; // otherwise we can keep the default (rounded) size
styleChanges.queueIfNeeded(aBrowser, roundedInline);
+ if (lastRoundedSize) {
+ // check wether the letterboxing margin is less than the border radius, and if so flatten the borders
+ let borderRadius = parseInt(win.getComputedStyle(browserContainer).getPropertyValue("--letterboxing-border-radius"));
+ if (borderRadius &&
+ (parentWidth - lastRoundedSize.width < borderRadius &&
+ parentHeight - lastRoundedSize.height < borderRadius)) {
+ borderRadius = 0;
+ } else {
+ borderRadius = "";
+ }
+ styleChanges.queueIfNeeded(browserParent, {
+ '--letterboxing-border-radius': borderRadius
+ });
+ }
+
// If the size of the content is already quantized, we do nothing.
if (!styleChanges.length) {
log(`${logPrefix} is_rounded == true`);
@@ -690,6 +721,10 @@ class _RFPHelper {
_updateSizeForTabsInWindow(aWindow) {
let tabBrowser = aWindow.gBrowser;
tabBrowser.tabpanels?.classList.add("letterboxing");
+ tabBrowser.tabpanels?.classList.toggle("letterboxing-vcenter",
+ Services.prefs.getBoolPref(kPrefLetterboxingVcenter, false));
+ tabBrowser.tabpanels?.classList.toggle("letterboxing-gradient",
+ Services.prefs.getBoolPref(kPrefLetterboxingGradient, false));
for (let tab of tabBrowser.tabs) {
let browser = tab.linkedBrowser;
View it on GitLab: https://gitlab.torproject.org/tpo/applications/tor-browser/-/compare/478dde…
--
View it on GitLab: https://gitlab.torproject.org/tpo/applications/tor-browser/-/compare/478dde…
You're receiving this email because of your account on gitlab.torproject.org.
[View Less]
1
0

[Git][tpo/applications/tor-browser][tor-browser-115.7.0esr-13.5-1] 3 commits: Temporary commit: manually place generated wasm files
by Pier Angelo Vendrame (@pierov) 26 Jan '24
by Pier Angelo Vendrame (@pierov) 26 Jan '24
26 Jan '24
Pier Angelo Vendrame pushed to branch tor-browser-115.7.0esr-13.5-1 at The Tor Project / Applications / Tor Browser
Commits:
ebfac0ab by Cecylia Bocovich at 2024-01-26T16:27:01+00:00
Temporary commit: manually place generated wasm files
These files are built reproducibly using tor-browser-build: https://gitlab.torproject.org/tpo/applications/tor-browser-build/-/merge_re…
We're manually adding them here while working on the interface, but
eventually these should be placed in the …
[View More]right location using
tor-browser-build.
- - - - -
10d5eb0b by Cecylia Bocovich at 2024-01-26T16:27:01+00:00
Lox integration
- - - - -
478ddecb by Cecylia Bocovich at 2024-01-26T16:27:01+00:00
fixup! Bug 40597: Implement TorSettings module
Implement Lox backend.
- - - - -
9 changed files:
- dom/security/nsContentSecurityUtils.cpp
- + toolkit/components/lox/Lox.sys.mjs
- + toolkit/components/lox/content/lox_wasm_bg.wasm
- + toolkit/components/lox/jar.mn
- + toolkit/components/lox/lox_wasm.jsm
- + toolkit/components/lox/moz.build
- toolkit/components/moz.build
- toolkit/components/tor-launcher/TorStartupService.sys.mjs
- toolkit/modules/TorSettings.sys.mjs
Changes:
=====================================
dom/security/nsContentSecurityUtils.cpp
=====================================
@@ -618,6 +618,9 @@ bool nsContentSecurityUtils::IsEvalAllowed(JSContext* cx,
// The Browser Toolbox/Console
"debugger"_ns,
+
+ // Tor Browser's Lox wasm integration
+ "resource://gre/modules/lox_wasm.jsm"_ns,
};
// We also permit two specific idioms in eval()-like contexts. We'd like to
=====================================
toolkit/components/lox/Lox.sys.mjs
=====================================
@@ -0,0 +1,801 @@
+import { XPCOMUtils } from "resource://gre/modules/XPCOMUtils.sys.mjs";
+import {
+ clearInterval,
+ setInterval,
+} from "resource://gre/modules/Timer.sys.mjs";
+
+const lazy = {};
+ChromeUtils.defineESModuleGetters(lazy, {
+ DomainFrontRequestBuilder:
+ "resource://gre/modules/DomainFrontedRequests.sys.mjs",
+ TorConnect: "resource://gre/modules/TorConnect.sys.mjs",
+ TorConnectState: "resource://gre/modules/TorConnect.sys.mjs",
+ TorSettings: "resource://gre/modules/TorSettings.sys.mjs",
+ TorSettingsTopics: "resource://gre/modules/TorSettings.sys.mjs",
+ TorBridgeSource: "resource://gre/modules/TorSettings.sys.mjs",
+});
+XPCOMUtils.defineLazyModuleGetters(lazy, {
+ init: "resource://gre/modules/lox_wasm.jsm",
+ open_invite: "resource://gre/modules/lox_wasm.jsm",
+ handle_new_lox_credential: "resource://gre/modules/lox_wasm.jsm",
+ set_panic_hook: "resource://gre/modules/lox_wasm.jsm",
+ invitation_is_trusted: "resource://gre/modules/lox_wasm.jsm",
+ issue_invite: "resource://gre/modules/lox_wasm.jsm",
+ prepare_invite: "resource://gre/modules/lox_wasm.jsm",
+ get_invites_remaining: "resource://gre/modules/lox_wasm.jsm",
+ get_trust_level: "resource://gre/modules/lox_wasm.jsm",
+ level_up: "resource://gre/modules/lox_wasm.jsm",
+ handle_level_up: "resource://gre/modules/lox_wasm.jsm",
+ trust_promotion: "resource://gre/modules/lox_wasm.jsm",
+ handle_trust_promotion: "resource://gre/modules/lox_wasm.jsm",
+ trust_migration: "resource://gre/modules/lox_wasm.jsm",
+ handle_trust_migration: "resource://gre/modules/lox_wasm.jsm",
+ get_next_unlock: "resource://gre/modules/lox_wasm.jsm",
+ check_blockage: "resource://gre/modules/lox_wasm.jsm",
+ handle_check_blockage: "resource://gre/modules/lox_wasm.jsm",
+ blockage_migration: "resource://gre/modules/lox_wasm.jsm",
+ handle_blockage_migration: "resource://gre/modules/lox_wasm.jsm",
+});
+
+export const LoxErrors = Object.freeze({
+ BadInvite: "BadInvite",
+ MissingCredential: "MissingCredential",
+ LoxServerUnreachable: "LoxServerUnreachable",
+ NoInvitations: "NoInvitations",
+ InitError: "InitializationError",
+ NotInitialized: "NotInitialized",
+});
+
+const LoxSettingsPrefs = Object.freeze({
+ /* string: the lox credential */
+ credentials: "lox.settings.credentials",
+ invites: "lox.settings.invites",
+ events: "lox.settings.events",
+ pubkeys: "lox.settings.pubkeys",
+ enctable: "lox.settings.enctable",
+ constants: "lox.settings.constants",
+});
+
+class LoxError extends Error {
+ constructor(type) {
+ super("");
+ this.type = type;
+ }
+}
+
+class LoxImpl {
+ #initialized = false;
+ #window = null;
+ #pubKeyPromise = null;
+ #encTablePromise = null;
+ #constantsPromise = null;
+ #domainFrontedRequests = null;
+ #invites = null;
+ #pubKeys = null;
+ #encTable = null;
+ #constants = null;
+ #credentials = null;
+ #events = [];
+ #backgroundInterval = null;
+
+ observe(subject, topic, data) {
+ switch (topic) {
+ case lazy.TorSettingsTopics.SettingsChanged:
+ const { changes } = subject.wrappedJSObject;
+ if (
+ changes.includes("bridges.enabled") ||
+ changes.includes("bridges.source") ||
+ changes.includes("bridges.lox_id")
+ ) {
+ // if lox_id has changed, clear event and invite queues
+ if (changes.includes("bridges.lox_id")) {
+ this.clearEventData();
+ this.clearInvites();
+ }
+
+ // Only run background tasks if Lox is enabled
+ if (this.#inuse) {
+ if (!this.#backgroundInterval) {
+ this.#backgroundInterval = setInterval(
+ this.#backgroundTasks.bind(this),
+ 1000 * 60 * 60 * 12
+ );
+ }
+ } else if (this.#backgroundInterval) {
+ clearInterval(this.#backgroundInterval);
+ this.#backgroundInterval = null;
+ }
+ }
+ break;
+ case lazy.TorSettingsTopics.Ready:
+ // Run background tasks every 12 hours if Lox is enabled
+ if (this.#inuse) {
+ this.#backgroundInterval = setInterval(
+ this.#backgroundTasks.bind(this),
+ 1000 * 60 * 60 * 12
+ );
+ }
+ break;
+ }
+ }
+
+ get #inuse() {
+ return (
+ lazy.TorSettings.bridges.enabled === true &&
+ lazy.TorSettings.bridges.source === lazy.TorBridgeSource.Lox &&
+ lazy.TorSettings.bridges.lox_id
+ );
+ }
+
+ /**
+ * Formats and returns bridges from the stored Lox credential
+ *
+ * @param {string} loxid The id string associated with a lox credential
+ *
+ * @returns {string[]} An array of formatted bridge lines. The array is empty
+ * if there are no bridges.
+ */
+ getBridges(loxid) {
+ if (!this.#initialized) {
+ throw new LoxError(LoxErrors.NotInitialized);
+ }
+ if (loxid === null) {
+ return [];
+ }
+ if (!this.#credentials[loxid]) {
+ // This lox id doesn't correspond to a stored credential
+ throw new LoxError(LoxErrors.MissingCredential);
+ }
+ // Note: this is messy now but can be mostly removed after we have
+ // https://gitlab.torproject.org/tpo/anti-censorship/lox/-/issues/46
+ let bridgelines = JSON.parse(this.#credentials[loxid]).bridgelines;
+ let bridges = [];
+ for (const bridge of bridgelines) {
+ let addr = bridge.addr;
+ while (addr[addr.length - 1] === 0) {
+ addr.pop();
+ }
+ addr = new Uint8Array(addr);
+ let decoder = new TextDecoder("utf-8");
+ addr = decoder.decode(addr);
+
+ let info = bridge.info;
+ while (info[info.length - 1] === 0) {
+ info.pop();
+ }
+ info = new Uint8Array(info);
+ info = decoder.decode(info);
+
+ let regexpTransport = /type=([a-zA-Z0-9]*)/;
+ let transport = info.match(regexpTransport);
+ if (transport !== null) {
+ transport = transport[1];
+ } else {
+ transport = "";
+ }
+
+ let regexpFingerprint = /fingerprint=\"([a-zA-Z0-9]*)\"/;
+ let fingerprint = info.match(regexpFingerprint);
+ if (fingerprint !== null) {
+ fingerprint = fingerprint[1];
+ } else {
+ fingerprint = "";
+ }
+
+ let regexpParams = /params=Some\(\{(.*)\}\)/;
+ let params = info.match(regexpParams);
+ if (params !== null) {
+ params = params[1]
+ .replaceAll('"', "")
+ .replaceAll(": ", "=")
+ .replaceAll(",", " ");
+ } else {
+ params = "";
+ }
+
+ bridges.push(
+ `${transport} ${addr}:${bridge.port} ${fingerprint} ${params}`
+ );
+ }
+ return bridges;
+ }
+
+ #store() {
+ Services.prefs.setStringPref(LoxSettingsPrefs.pubkeys, this.#pubKeys);
+ Services.prefs.setStringPref(LoxSettingsPrefs.enctable, this.#encTable);
+ Services.prefs.setStringPref(LoxSettingsPrefs.constants, this.#constants);
+ Services.prefs.setStringPref(
+ LoxSettingsPrefs.credentials,
+ JSON.stringify(this.#credentials)
+ );
+ Services.prefs.setStringPref(
+ LoxSettingsPrefs.invites,
+ JSON.stringify(this.#invites)
+ );
+ Services.prefs.setStringPref(
+ LoxSettingsPrefs.events,
+ JSON.stringify(this.#events)
+ );
+ }
+
+ #load() {
+ if (this.#credentials === null) {
+ let cred = Services.prefs.getStringPref(LoxSettingsPrefs.credentials, "");
+ this.#credentials = cred !== "" ? JSON.parse(cred) : {};
+ let invites = Services.prefs.getStringPref(LoxSettingsPrefs.invites, "");
+ if (invites !== "") {
+ this.#invites = JSON.parse(invites);
+ }
+ let events = Services.prefs.getStringPref(LoxSettingsPrefs.events, "");
+ if (events !== "") {
+ this.#events = JSON.parse(events);
+ }
+ }
+ this.#pubKeys = Services.prefs.getStringPref(
+ LoxSettingsPrefs.pubkeys,
+ null
+ );
+ this.#encTable = Services.prefs.getStringPref(
+ LoxSettingsPrefs.enctable,
+ null
+ );
+ this.#constants = Services.prefs.getStringPref(
+ LoxSettingsPrefs.constants,
+ null
+ );
+ }
+
+ async #getPubKeys() {
+ if (this.#pubKeyPromise === null) {
+ this.#pubKeyPromise = this.#makeRequest("pubkeys", [])
+ .then(pubKeys => {
+ this.#pubKeys = JSON.stringify(pubKeys);
+ })
+ .catch(() => {
+ // We always try to update, but if that doesn't work fall back to stored data
+ if (!this.#pubKeys) {
+ throw new LoxError(LoxErrors.LoxServerUnreachable);
+ }
+ });
+ }
+ await this.#pubKeyPromise;
+ }
+
+ async #getEncTable() {
+ if (this.#encTablePromise === null) {
+ this.#encTablePromise = this.#makeRequest("reachability", [])
+ .then(encTable => {
+ this.#encTable = JSON.stringify(encTable);
+ })
+ .catch(() => {
+ // Try to update first, but if that doesn't work fall back to stored data
+ if (!this.#encTable) {
+ throw new LoxError(LoxErrors.LoxServerUnreachable);
+ }
+ });
+ }
+ await this.#encTablePromise;
+ }
+
+ async #getConstants() {
+ if (this.#constantsPromise === null) {
+ // Try to update first, but if that doesn't work fall back to stored data
+ this.#constantsPromise = this.#makeRequest("constants", [])
+ .then(constants => {
+ this.#constants = JSON.stringify(constants);
+ })
+ .catch(() => {
+ if (!this.#constants) {
+ throw new LoxError(LoxErrors.LoxServerUnreachable);
+ }
+ });
+ }
+ await this.#constantsPromise;
+ }
+
+ /**
+ * Check for blockages and attempt to perform a levelup
+ *
+ * If either blockages or a levelup happened, add an event to the event queue
+ */
+ async #backgroundTasks() {
+ if (!this.#initialized) {
+ throw new LoxError(LoxErrors.NotInitialized);
+ }
+ const loxid = lazy.TorSettings.bridges.lox_id;
+ try {
+ const levelup = await this.#attemptUpgrade(loxid);
+ if (levelup) {
+ const level = lazy.get_trust_level(this.#credentials[loxid]);
+ const newEvent = {
+ type: "levelup",
+ newlevel: level,
+ };
+ this.#events.push(newEvent);
+ this.#store();
+ }
+ } catch (err) {
+ console.log(err);
+ }
+ try {
+ const leveldown = await this.#blockageMigration(loxid);
+ if (leveldown) {
+ let level = lazy.get_trust_level(this.#credentials[loxid]);
+ const newEvent = {
+ type: "blockage",
+ newlevel: level,
+ };
+ this.#events.push(newEvent);
+ this.#store();
+ }
+ } catch (err) {
+ console.log(err);
+ }
+ }
+
+ /**
+ * Generates a new random lox id to be associated with an invitation/credential
+ */
+ #genLoxId() {
+ return crypto.randomUUID();
+ }
+
+ async init() {
+ // If lox_id is set, load it
+ Services.obs.addObserver(this, lazy.TorSettingsTopics.SettingsChanged);
+ Services.obs.addObserver(this, lazy.TorSettingsTopics.Ready);
+
+ // Hack to make the generated wasm happy
+ this.#window = {
+ crypto,
+ };
+ this.#window.window = this.#window;
+ await lazy.init(this.#window);
+ lazy.set_panic_hook();
+ if (typeof lazy.open_invite !== "function") {
+ throw new LoxError(LoxErrors.InitError);
+ }
+ this.#invites = [];
+ this.#events = [];
+ this.#load();
+ this.#initialized = true;
+ }
+
+ async uninit() {
+ Services.obs.removeObserver(this, lazy.TorSettingsTopics.SettingsChanged);
+ Services.obs.removeObserver(this, lazy.TorSettingsTopics.Ready);
+ if (this.#domainFrontedRequests !== null) {
+ try {
+ const domainFronting = await this.#domainFrontedRequests;
+ domainFronting.uninit();
+ } catch {}
+ this.#domainFrontedRequests = null;
+ }
+ this.#initialized = false;
+ this.#window = null;
+ this.#invites = null;
+ this.#pubKeys = null;
+ this.#encTable = null;
+ this.#constants = null;
+ this.#pubKeyPromise = null;
+ this.#encTablePromise = null;
+ this.#constantsPromise = null;
+ this.#credentials = null;
+ this.#events = [];
+ if (this.#backgroundInterval) {
+ clearInterval(this.#backgroundInterval);
+ }
+ this.#backgroundInterval = null;
+ }
+
+ /**
+ * Parses an input string to check if it is a valid Lox invitation
+ *
+ * @param {string} invite A Lox invitation
+ * @returns {Promise<bool>} A promise that resolves to true if the value passed
+ * in was a Lox invitation and false if it is not
+ */
+ async validateInvitation(invite) {
+ if (!this.#initialized) {
+ throw new LoxError(LoxErrors.NotInitialized);
+ }
+ try {
+ await lazy.invitation_is_trusted(invite);
+ } catch (err) {
+ console.log(err);
+ return false;
+ }
+ return true;
+ }
+
+ // Note: This is only here for testing purposes. We're going to be using telegram
+ // to issue open invitations for Lox bridges.
+ async requestOpenInvite() {
+ if (!this.#initialized) {
+ throw new LoxError(LoxErrors.NotInitialized);
+ }
+ let invite = await this.#makeRequest("invite", []);
+ console.log(invite);
+ return invite;
+ }
+
+ /**
+ * Redeems a Lox invitation to obtain a credential and bridges
+ *
+ * @param {string} invite A Lox invitation
+ * @returns {Promise<string>} A promise with the loxid of the associated credential on success
+ */
+ async redeemInvite(invite) {
+ if (!this.#initialized) {
+ throw new LoxError(LoxErrors.NotInitialized);
+ }
+ await this.#getPubKeys();
+ let request = await lazy.open_invite(invite.invite);
+ let id = this.#genLoxId();
+ let response = await this.#makeRequest(
+ "openreq",
+ JSON.parse(request).request
+ );
+ console.log("openreq response: ", response);
+ if (response.hasOwnProperty("error")) {
+ throw new LoxError(LoxErrors.BadInvite);
+ }
+ let cred = lazy.handle_new_lox_credential(
+ request,
+ JSON.stringify(response),
+ this.#pubKeys
+ );
+ this.#credentials[id] = cred;
+ this.#store();
+ return id;
+ }
+
+ /**
+ * Get metadata on all invites historically generated by this credential
+ *
+ * @returns {object[]} A list of all historical invites
+ */
+ getInvites() {
+ if (!this.#initialized) {
+ throw new LoxError(LoxErrors.NotInitialized);
+ }
+ return this.#invites;
+ }
+
+ /**
+ * Generates a new trusted Lox invitation that a user can pass to their contacts
+ *
+ * @returns {Promise<string>} A promise that resolves to a valid Lox invitation. The promise
+ * will reject if:
+ * - there is no saved Lox credential
+ * - the saved credential does not have any invitations available
+ */
+ async generateInvite() {
+ if (!this.#initialized) {
+ throw new LoxError(LoxErrors.NotInitialized);
+ }
+ const loxid = lazy.TorSettings.bridges.lox_id;
+ if (!loxid || !this.#credentials[loxid]) {
+ throw new LoxError(LoxErrors.MissingCredential);
+ }
+ await this.#getPubKeys();
+ await this.#getEncTable();
+ let level = lazy.get_trust_level(this.#credentials[loxid]);
+ if (level < 1) {
+ throw new LoxError(LoxErrors.NoInvitations);
+ }
+ let request = lazy.issue_invite(
+ JSON.stringify(this.#credentials[loxid]),
+ this.#encTable,
+ this.#pubKeys
+ );
+ let response;
+ try {
+ response = await this.#makeRequest(
+ "issueinvite",
+ JSON.parse(request).request
+ );
+ } catch {
+ throw new LoxError(LoxErrors.LoxServerUnreachable);
+ }
+ if (response.hasOwnProperty("error")) {
+ console.log(response.error);
+ throw new LoxError(LoxErrors.NoInvitations);
+ } else {
+ this.#credentials[loxid] = response;
+ const invite = lazy.prepare_invite(response);
+ this.#invites.push(invite);
+ // cap length of stored invites
+ if (this.#invites.len > 50) {
+ this.#invites.shift();
+ }
+ return invite;
+ }
+ }
+
+ /**
+ * Get the number of invites that a user has remaining
+ *
+ * @returns {Promise<int>} A promise with the number of invites that can still be generated
+ * by a user's credential. This promise will reject if:
+ * - There is no credential
+ */
+ getRemainingInviteCount() {
+ if (!this.#initialized) {
+ throw new LoxError(LoxErrors.NotInitialized);
+ }
+ const loxid = lazy.TorSettings.bridges.lox_id;
+ if (!loxid || !this.#credentials[loxid]) {
+ throw new LoxError(LoxErrors.MissingCredential);
+ }
+ return parseInt(lazy.get_invites_remaining(this.#credentials[loxid]));
+ }
+
+ async #blockageMigration(loxid) {
+ if (!loxid || !this.#credentials[loxid]) {
+ throw new LoxError(LoxErrors.MissingCredential);
+ }
+ await this.#getPubKeys();
+ let request;
+ try {
+ request = lazy.check_blockage(this.#credentials[loxid], this.#pubKeys);
+ } catch {
+ console.log("Not ready for blockage migration");
+ return false;
+ }
+ let response = await this.#makeRequest("checkblockage", request);
+ if (response.hasOwnProperty("error")) {
+ console.log(response.error);
+ throw new LoxError(LoxErrors.LoxServerUnreachable);
+ }
+ const migrationCred = lazy.handle_check_blockage(
+ this.#credentials[loxid],
+ JSON.stringify(response)
+ );
+ request = lazy.blockage_migration(
+ this.#credentials[loxid],
+ migrationCred,
+ this.#pubKeys
+ );
+ response = await this.#makeRequest("blockagemigration", request);
+ if (response.hasOwnProperty("error")) {
+ console.log(response.error);
+ throw new LoxError(LoxErrors.LoxServerUnreachable);
+ }
+ const cred = lazy.handle_blockage_migration(
+ this.#credentials[loxid],
+ JSON.stringify(response),
+ this.#pubKeys
+ );
+ this.#credentials[loxid] = cred;
+ this.#store();
+ return true;
+ }
+
+ /** Attempts to upgrade the currently saved Lox credential.
+ * If an upgrade is available, save an event in the event list.
+ *
+ * @returns {boolean} whether a levelup event occured
+ */
+ async #attemptUpgrade(loxid) {
+ if (!loxid || !this.#credentials[loxid]) {
+ throw new LoxError(LoxErrors.MissingCredential);
+ }
+ await this.#getPubKeys();
+ await this.#getEncTable();
+ await this.#getConstants();
+ let success = false;
+ let level = lazy.get_trust_level(this.#credentials[loxid]);
+ if (level < 1) {
+ // attempt trust promotion instead
+ try {
+ success = await this.#trustMigration();
+ } catch (err) {
+ console.log(err);
+ return false;
+ }
+ } else {
+ let request = lazy.level_up(
+ this.#credentials[loxid],
+ this.#encTable,
+ this.#pubKeys
+ );
+ const response = await this.#makeRequest("levelup", request);
+ if (response.hasOwnProperty("error")) {
+ console.log(response.error);
+ throw new LoxError(LoxErrors.LoxServerUnreachable);
+ }
+ const cred = lazy.handle_level_up(
+ request,
+ JSON.stringify(response),
+ this.#pubKeys
+ );
+ this.#credentials[loxid] = cred;
+ return true;
+ }
+ return success;
+ }
+
+ /**
+ * Attempt to migrate from an untrusted to a trusted Lox credential
+ *
+ * @returns {Promise<bool>} A bool value indicated whether the credential
+ * was successfully migrated.
+ */
+ async #trustMigration() {
+ const loxid = lazy.TorSettings.bridges.lox_id;
+ if (!loxid || !this.#credentials[loxid]) {
+ throw new LoxError(LoxErrors.MissingCredential);
+ }
+ await this.#getPubKeys();
+ return new Promise((resolve, reject) => {
+ let request = "";
+ try {
+ request = lazy.trust_promotion(this.#credentials[loxid], this.#pubKeys);
+ } catch (err) {
+ console.log("Not ready to upgrade");
+ resolve(false);
+ }
+ this.#makeRequest("trustpromo", JSON.parse(request).request)
+ .then(response => {
+ if (response.hasOwnProperty("error")) {
+ resolve(false);
+ }
+ console.log("Got promotion cred");
+ console.log(response);
+ console.log(request);
+ let promoCred = lazy.handle_trust_promotion(
+ request,
+ JSON.stringify(response)
+ );
+ console.log("Formatted promotion cred");
+ request = lazy.trust_migration(
+ this.#credentials[loxid],
+ promoCred,
+ this.#pubKeys
+ );
+ console.log("Formatted migration request");
+ this.#makeRequest("trustmig", JSON.parse(request).request)
+ .then(response => {
+ if (response.hasOwnProperty("error")) {
+ resolve(false);
+ }
+ console.log("Got new credential");
+ let cred = lazy.handle_trust_migration(request, response);
+ this.#credentials[loxid] = cred;
+ this.#store();
+ resolve(true);
+ })
+ .catch(err => {
+ console.log(err);
+ console.log("Failed trust migration");
+ resolve(false);
+ });
+ })
+ .catch(err => {
+ console.log(err);
+ console.log("Failed trust promotion");
+ resolve(false);
+ });
+ });
+ }
+
+ /**
+ * @typedef {object} EventData
+ *
+ * @property {string} [type] - the type of event. This should be one of:
+ * ("levelup", "blockage")
+ * @property {integer} [newlevel] - the new level, after the event. Levels count
+ * from 0, but "blockage" events can never take the user to 0, so this will always
+ * be 1 or greater.
+ */
+
+ /**
+ * Get a list of accumulated events
+ *
+ * @returns {Promise<EventData[]>} A promise with a list of the accumulated,
+ * unacknowledged events associated with a user's credential. This promise will reject if
+ * - There is no credential
+ */
+ getEventData() {
+ if (!this.#initialized) {
+ throw new LoxError(LoxErrors.NotInitialized);
+ }
+ const loxid = lazy.TorSettings.bridges.lox_id;
+ if (!loxid || !this.#credentials[loxid]) {
+ throw new LoxError(LoxErrors.MissingCredential);
+ }
+ return this.#events;
+ }
+
+ /**
+ * Clears accumulated event data
+ */
+ clearEventData() {
+ if (!this.#initialized) {
+ throw new LoxError(LoxErrors.NotInitialized);
+ }
+ this.#events = [];
+ this.#store();
+ }
+
+ /**
+ * Clears accumulated invitations
+ */
+ clearInvites() {
+ if (!this.#initialized) {
+ throw new LoxError(LoxErrors.NotInitialized);
+ }
+ this.#invites = [];
+ this.#store();
+ }
+
+ /**
+ * @typedef {object} UnlockData
+ *
+ * @property {string} date - The date-time for the next level up, formatted as YYYY-MM-DDTHH:mm:ssZ.
+ * @property {integer} nextLevel - The next level. Levels count from 0, so this will be 1 or greater.
+ *
+ */
+
+ /**
+ * Get dates at which access to new features will unlock
+ */
+ async getNextUnlock() {
+ if (!this.#initialized) {
+ throw new LoxError(LoxErrors.NotInitialized);
+ }
+ const loxid = lazy.TorSettings.bridges.lox_id;
+ if (!loxid || !this.#credentials[loxid]) {
+ throw new LoxError(LoxErrors.MissingCredential);
+ }
+ await this.#getConstants();
+ let nextUnlocks = JSON.parse(
+ lazy.get_next_unlock(this.#constants, this.#credentials[loxid])
+ );
+ const level = lazy.get_trust_level(this.#credentials[loxid]);
+ const unlocks = {
+ date: nextUnlocks.trust_level_unlock_date,
+ level: level + 1,
+ };
+ return unlocks;
+ }
+
+ async #makeRequest(procedure, args) {
+ // TODO: Customize to for Lox
+ const serviceUrl = "https://rdsys-frontend-01.torproject.org/lox";
+ const url = `${serviceUrl}/${procedure}`;
+
+ if (lazy.TorConnect.state === lazy.TorConnectState.Bootstrapped) {
+ const request = await fetch(url, {
+ method: "POST",
+ headers: {
+ "Content-Type": "application/vnd.api+json",
+ },
+ body: JSON.stringify(args),
+ });
+ return request.json();
+ }
+
+ if (this.#domainFrontedRequests === null) {
+ this.#domainFrontedRequests = new Promise((resolve, reject) => {
+ // TODO: Customize to the values for Lox
+ const reflector = Services.prefs.getStringPref(
+ "extensions.torlauncher.bridgedb_reflector"
+ );
+ const front = Services.prefs.getStringPref(
+ "extensions.torlauncher.bridgedb_front"
+ );
+ const builder = new lazy.DomainFrontRequestBuilder();
+ builder
+ .init(reflector, front)
+ .then(() => resolve(builder))
+ .catch(reject);
+ });
+ }
+ const builder = await this.#domainFrontedRequests;
+ return builder.buildPostRequest(url, args);
+ }
+}
+
+export const Lox = new LoxImpl();
=====================================
toolkit/components/lox/content/lox_wasm_bg.wasm
=====================================
Binary files /dev/null and b/toolkit/components/lox/content/lox_wasm_bg.wasm differ
=====================================
toolkit/components/lox/jar.mn
=====================================
@@ -0,0 +1,2 @@
+toolkit.jar:
+ content/global/lox/lox_wasm_bg.wasm (content/lox_wasm_bg.wasm)
=====================================
toolkit/components/lox/lox_wasm.jsm
=====================================
@@ -0,0 +1,1217 @@
+var EXPORTED_SYMBOLS = ["set_panic_hook", "open_invite", "handle_new_lox_credential", "trust_promotion", "handle_trust_promotion", "trust_migration", "handle_trust_migration", "level_up", "handle_level_up", "issue_invite", "handle_issue_invite", "prepare_invite", "redeem_invite", "handle_redeem_invite", "check_blockage", "handle_check_blockage", "blockage_migration", "handle_blockage_migration", "get_last_upgrade_time", "get_trust_level", "get_invites_remaining", "get_issued_invite_expiry", "get_received_invite_expiry", "get_bridgelines_from_bucket", "invitation_is_trusted", "get_next_unlock", "init", "initSync"];
+
+let wasm;
+let module;
+
+const heap = new Array(128).fill(undefined);
+
+heap.push(undefined, null, true, false);
+
+function getObject(idx) { return heap[idx]; }
+
+let heap_next = heap.length;
+
+function dropObject(idx) {
+ if (idx < 132) return;
+ heap[idx] = heap_next;
+ heap_next = idx;
+}
+
+function takeObject(idx) {
+ const ret = getObject(idx);
+ dropObject(idx);
+ return ret;
+}
+
+const cachedTextDecoder = (typeof TextDecoder !== 'undefined' ? new TextDecoder('utf-8', { ignoreBOM: true, fatal: true }) : { decode: () => { throw Error('TextDecoder not available') } } );
+
+if (typeof TextDecoder !== 'undefined') { cachedTextDecoder.decode(); };
+
+let cachedUint8Memory0 = null;
+
+function getUint8Memory0() {
+ if (cachedUint8Memory0 === null || cachedUint8Memory0.byteLength === 0) {
+ cachedUint8Memory0 = new Uint8Array(wasm.memory.buffer);
+ }
+ return cachedUint8Memory0;
+}
+
+function getStringFromWasm0(ptr, len) {
+ ptr = ptr >>> 0;
+ return cachedTextDecoder.decode(getUint8Memory0().subarray(ptr, ptr + len));
+}
+
+function addHeapObject(obj) {
+ if (heap_next === heap.length) heap.push(heap.length + 1);
+ const idx = heap_next;
+ heap_next = heap[idx];
+
+ heap[idx] = obj;
+ return idx;
+}
+/**
+*/
+function set_panic_hook() {
+ wasm.set_panic_hook();
+}
+
+let WASM_VECTOR_LEN = 0;
+
+function passArray8ToWasm0(arg, malloc) {
+ const ptr = malloc(arg.length * 1, 1) >>> 0;
+ getUint8Memory0().set(arg, ptr / 1);
+ WASM_VECTOR_LEN = arg.length;
+ return ptr;
+}
+
+let cachedInt32Memory0 = null;
+
+function getInt32Memory0() {
+ if (cachedInt32Memory0 === null || cachedInt32Memory0.byteLength === 0) {
+ cachedInt32Memory0 = new Int32Array(wasm.memory.buffer);
+ }
+ return cachedInt32Memory0;
+}
+/**
+* @param {Uint8Array} invite
+* @returns {string}
+*/
+function open_invite(invite) {
+ let deferred3_0;
+ let deferred3_1;
+ try {
+ const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
+ const ptr0 = passArray8ToWasm0(invite, wasm.__wbindgen_malloc);
+ const len0 = WASM_VECTOR_LEN;
+ wasm.open_invite(retptr, ptr0, len0);
+ var r0 = getInt32Memory0()[retptr / 4 + 0];
+ var r1 = getInt32Memory0()[retptr / 4 + 1];
+ var r2 = getInt32Memory0()[retptr / 4 + 2];
+ var r3 = getInt32Memory0()[retptr / 4 + 3];
+ var ptr2 = r0;
+ var len2 = r1;
+ if (r3) {
+ ptr2 = 0; len2 = 0;
+ throw takeObject(r2);
+ }
+ deferred3_0 = ptr2;
+ deferred3_1 = len2;
+ return getStringFromWasm0(ptr2, len2);
+ } finally {
+ wasm.__wbindgen_add_to_stack_pointer(16);
+ wasm.__wbindgen_free(deferred3_0, deferred3_1, 1);
+ }
+}
+
+const cachedTextEncoder = (typeof TextEncoder !== 'undefined' ? new TextEncoder('utf-8') : { encode: () => { throw Error('TextEncoder not available') } } );
+
+const encodeString = (typeof cachedTextEncoder.encodeInto === 'function'
+ ? function (arg, view) {
+ return cachedTextEncoder.encodeInto(arg, view);
+}
+ : function (arg, view) {
+ const buf = cachedTextEncoder.encode(arg);
+ view.set(buf);
+ return {
+ read: arg.length,
+ written: buf.length
+ };
+});
+
+function passStringToWasm0(arg, malloc, realloc) {
+
+ if (realloc === undefined) {
+ const buf = cachedTextEncoder.encode(arg);
+ const ptr = malloc(buf.length, 1) >>> 0;
+ getUint8Memory0().subarray(ptr, ptr + buf.length).set(buf);
+ WASM_VECTOR_LEN = buf.length;
+ return ptr;
+ }
+
+ let len = arg.length;
+ let ptr = malloc(len, 1) >>> 0;
+
+ const mem = getUint8Memory0();
+
+ let offset = 0;
+
+ for (; offset < len; offset++) {
+ const code = arg.charCodeAt(offset);
+ if (code > 0x7F) break;
+ mem[ptr + offset] = code;
+ }
+
+ if (offset !== len) {
+ if (offset !== 0) {
+ arg = arg.slice(offset);
+ }
+ ptr = realloc(ptr, len, len = offset + arg.length * 3, 1) >>> 0;
+ const view = getUint8Memory0().subarray(ptr + offset, ptr + len);
+ const ret = encodeString(arg, view);
+
+ offset += ret.written;
+ }
+
+ WASM_VECTOR_LEN = offset;
+ return ptr;
+}
+/**
+* @param {string} open_lox_result
+* @param {string} open_lox_response
+* @param {string} lox_pub
+* @returns {string}
+*/
+function handle_new_lox_credential(open_lox_result, open_lox_response, lox_pub) {
+ let deferred5_0;
+ let deferred5_1;
+ try {
+ const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
+ const ptr0 = passStringToWasm0(open_lox_result, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
+ const len0 = WASM_VECTOR_LEN;
+ const ptr1 = passStringToWasm0(open_lox_response, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
+ const len1 = WASM_VECTOR_LEN;
+ const ptr2 = passStringToWasm0(lox_pub, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
+ const len2 = WASM_VECTOR_LEN;
+ wasm.handle_new_lox_credential(retptr, ptr0, len0, ptr1, len1, ptr2, len2);
+ var r0 = getInt32Memory0()[retptr / 4 + 0];
+ var r1 = getInt32Memory0()[retptr / 4 + 1];
+ var r2 = getInt32Memory0()[retptr / 4 + 2];
+ var r3 = getInt32Memory0()[retptr / 4 + 3];
+ var ptr4 = r0;
+ var len4 = r1;
+ if (r3) {
+ ptr4 = 0; len4 = 0;
+ throw takeObject(r2);
+ }
+ deferred5_0 = ptr4;
+ deferred5_1 = len4;
+ return getStringFromWasm0(ptr4, len4);
+ } finally {
+ wasm.__wbindgen_add_to_stack_pointer(16);
+ wasm.__wbindgen_free(deferred5_0, deferred5_1, 1);
+ }
+}
+
+/**
+* @param {string} open_lox_cred
+* @param {string} lox_pub
+* @returns {string}
+*/
+function trust_promotion(open_lox_cred, lox_pub) {
+ let deferred4_0;
+ let deferred4_1;
+ try {
+ const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
+ const ptr0 = passStringToWasm0(open_lox_cred, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
+ const len0 = WASM_VECTOR_LEN;
+ const ptr1 = passStringToWasm0(lox_pub, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
+ const len1 = WASM_VECTOR_LEN;
+ wasm.trust_promotion(retptr, ptr0, len0, ptr1, len1);
+ var r0 = getInt32Memory0()[retptr / 4 + 0];
+ var r1 = getInt32Memory0()[retptr / 4 + 1];
+ var r2 = getInt32Memory0()[retptr / 4 + 2];
+ var r3 = getInt32Memory0()[retptr / 4 + 3];
+ var ptr3 = r0;
+ var len3 = r1;
+ if (r3) {
+ ptr3 = 0; len3 = 0;
+ throw takeObject(r2);
+ }
+ deferred4_0 = ptr3;
+ deferred4_1 = len3;
+ return getStringFromWasm0(ptr3, len3);
+ } finally {
+ wasm.__wbindgen_add_to_stack_pointer(16);
+ wasm.__wbindgen_free(deferred4_0, deferred4_1, 1);
+ }
+}
+
+/**
+* @param {string} trust_promo_request
+* @param {string} trust_promo_response
+* @returns {string}
+*/
+function handle_trust_promotion(trust_promo_request, trust_promo_response) {
+ let deferred4_0;
+ let deferred4_1;
+ try {
+ const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
+ const ptr0 = passStringToWasm0(trust_promo_request, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
+ const len0 = WASM_VECTOR_LEN;
+ const ptr1 = passStringToWasm0(trust_promo_response, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
+ const len1 = WASM_VECTOR_LEN;
+ wasm.handle_trust_promotion(retptr, ptr0, len0, ptr1, len1);
+ var r0 = getInt32Memory0()[retptr / 4 + 0];
+ var r1 = getInt32Memory0()[retptr / 4 + 1];
+ var r2 = getInt32Memory0()[retptr / 4 + 2];
+ var r3 = getInt32Memory0()[retptr / 4 + 3];
+ var ptr3 = r0;
+ var len3 = r1;
+ if (r3) {
+ ptr3 = 0; len3 = 0;
+ throw takeObject(r2);
+ }
+ deferred4_0 = ptr3;
+ deferred4_1 = len3;
+ return getStringFromWasm0(ptr3, len3);
+ } finally {
+ wasm.__wbindgen_add_to_stack_pointer(16);
+ wasm.__wbindgen_free(deferred4_0, deferred4_1, 1);
+ }
+}
+
+/**
+* @param {string} open_lox_cred
+* @param {string} trust_promo_cred
+* @param {string} lox_pub
+* @returns {string}
+*/
+function trust_migration(open_lox_cred, trust_promo_cred, lox_pub) {
+ let deferred5_0;
+ let deferred5_1;
+ try {
+ const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
+ const ptr0 = passStringToWasm0(open_lox_cred, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
+ const len0 = WASM_VECTOR_LEN;
+ const ptr1 = passStringToWasm0(trust_promo_cred, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
+ const len1 = WASM_VECTOR_LEN;
+ const ptr2 = passStringToWasm0(lox_pub, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
+ const len2 = WASM_VECTOR_LEN;
+ wasm.trust_migration(retptr, ptr0, len0, ptr1, len1, ptr2, len2);
+ var r0 = getInt32Memory0()[retptr / 4 + 0];
+ var r1 = getInt32Memory0()[retptr / 4 + 1];
+ var r2 = getInt32Memory0()[retptr / 4 + 2];
+ var r3 = getInt32Memory0()[retptr / 4 + 3];
+ var ptr4 = r0;
+ var len4 = r1;
+ if (r3) {
+ ptr4 = 0; len4 = 0;
+ throw takeObject(r2);
+ }
+ deferred5_0 = ptr4;
+ deferred5_1 = len4;
+ return getStringFromWasm0(ptr4, len4);
+ } finally {
+ wasm.__wbindgen_add_to_stack_pointer(16);
+ wasm.__wbindgen_free(deferred5_0, deferred5_1, 1);
+ }
+}
+
+/**
+* @param {string} trust_migration_request
+* @param {string} trust_migration_response
+* @param {string} lox_pub
+* @returns {string}
+*/
+function handle_trust_migration(trust_migration_request, trust_migration_response, lox_pub) {
+ let deferred5_0;
+ let deferred5_1;
+ try {
+ const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
+ const ptr0 = passStringToWasm0(trust_migration_request, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
+ const len0 = WASM_VECTOR_LEN;
+ const ptr1 = passStringToWasm0(trust_migration_response, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
+ const len1 = WASM_VECTOR_LEN;
+ const ptr2 = passStringToWasm0(lox_pub, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
+ const len2 = WASM_VECTOR_LEN;
+ wasm.handle_trust_migration(retptr, ptr0, len0, ptr1, len1, ptr2, len2);
+ var r0 = getInt32Memory0()[retptr / 4 + 0];
+ var r1 = getInt32Memory0()[retptr / 4 + 1];
+ var r2 = getInt32Memory0()[retptr / 4 + 2];
+ var r3 = getInt32Memory0()[retptr / 4 + 3];
+ var ptr4 = r0;
+ var len4 = r1;
+ if (r3) {
+ ptr4 = 0; len4 = 0;
+ throw takeObject(r2);
+ }
+ deferred5_0 = ptr4;
+ deferred5_1 = len4;
+ return getStringFromWasm0(ptr4, len4);
+ } finally {
+ wasm.__wbindgen_add_to_stack_pointer(16);
+ wasm.__wbindgen_free(deferred5_0, deferred5_1, 1);
+ }
+}
+
+/**
+* @param {string} level_one_cred
+* @param {string} encrypted_table
+* @param {string} lox_pub
+* @returns {string}
+*/
+function level_up(level_one_cred, encrypted_table, lox_pub) {
+ let deferred5_0;
+ let deferred5_1;
+ try {
+ const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
+ const ptr0 = passStringToWasm0(level_one_cred, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
+ const len0 = WASM_VECTOR_LEN;
+ const ptr1 = passStringToWasm0(encrypted_table, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
+ const len1 = WASM_VECTOR_LEN;
+ const ptr2 = passStringToWasm0(lox_pub, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
+ const len2 = WASM_VECTOR_LEN;
+ wasm.level_up(retptr, ptr0, len0, ptr1, len1, ptr2, len2);
+ var r0 = getInt32Memory0()[retptr / 4 + 0];
+ var r1 = getInt32Memory0()[retptr / 4 + 1];
+ var r2 = getInt32Memory0()[retptr / 4 + 2];
+ var r3 = getInt32Memory0()[retptr / 4 + 3];
+ var ptr4 = r0;
+ var len4 = r1;
+ if (r3) {
+ ptr4 = 0; len4 = 0;
+ throw takeObject(r2);
+ }
+ deferred5_0 = ptr4;
+ deferred5_1 = len4;
+ return getStringFromWasm0(ptr4, len4);
+ } finally {
+ wasm.__wbindgen_add_to_stack_pointer(16);
+ wasm.__wbindgen_free(deferred5_0, deferred5_1, 1);
+ }
+}
+
+/**
+* @param {string} levelup_request
+* @param {string} levelup_response
+* @param {string} lox_pub
+* @returns {string}
+*/
+function handle_level_up(levelup_request, levelup_response, lox_pub) {
+ let deferred5_0;
+ let deferred5_1;
+ try {
+ const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
+ const ptr0 = passStringToWasm0(levelup_request, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
+ const len0 = WASM_VECTOR_LEN;
+ const ptr1 = passStringToWasm0(levelup_response, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
+ const len1 = WASM_VECTOR_LEN;
+ const ptr2 = passStringToWasm0(lox_pub, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
+ const len2 = WASM_VECTOR_LEN;
+ wasm.handle_level_up(retptr, ptr0, len0, ptr1, len1, ptr2, len2);
+ var r0 = getInt32Memory0()[retptr / 4 + 0];
+ var r1 = getInt32Memory0()[retptr / 4 + 1];
+ var r2 = getInt32Memory0()[retptr / 4 + 2];
+ var r3 = getInt32Memory0()[retptr / 4 + 3];
+ var ptr4 = r0;
+ var len4 = r1;
+ if (r3) {
+ ptr4 = 0; len4 = 0;
+ throw takeObject(r2);
+ }
+ deferred5_0 = ptr4;
+ deferred5_1 = len4;
+ return getStringFromWasm0(ptr4, len4);
+ } finally {
+ wasm.__wbindgen_add_to_stack_pointer(16);
+ wasm.__wbindgen_free(deferred5_0, deferred5_1, 1);
+ }
+}
+
+/**
+* @param {string} trusted_cred
+* @param {string} encrypted_table
+* @param {string} lox_pub
+* @returns {string}
+*/
+function issue_invite(trusted_cred, encrypted_table, lox_pub) {
+ let deferred5_0;
+ let deferred5_1;
+ try {
+ const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
+ const ptr0 = passStringToWasm0(trusted_cred, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
+ const len0 = WASM_VECTOR_LEN;
+ const ptr1 = passStringToWasm0(encrypted_table, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
+ const len1 = WASM_VECTOR_LEN;
+ const ptr2 = passStringToWasm0(lox_pub, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
+ const len2 = WASM_VECTOR_LEN;
+ wasm.issue_invite(retptr, ptr0, len0, ptr1, len1, ptr2, len2);
+ var r0 = getInt32Memory0()[retptr / 4 + 0];
+ var r1 = getInt32Memory0()[retptr / 4 + 1];
+ var r2 = getInt32Memory0()[retptr / 4 + 2];
+ var r3 = getInt32Memory0()[retptr / 4 + 3];
+ var ptr4 = r0;
+ var len4 = r1;
+ if (r3) {
+ ptr4 = 0; len4 = 0;
+ throw takeObject(r2);
+ }
+ deferred5_0 = ptr4;
+ deferred5_1 = len4;
+ return getStringFromWasm0(ptr4, len4);
+ } finally {
+ wasm.__wbindgen_add_to_stack_pointer(16);
+ wasm.__wbindgen_free(deferred5_0, deferred5_1, 1);
+ }
+}
+
+/**
+* @param {string} issue_invite_request
+* @param {string} issue_invite_response
+* @param {string} lox_pub
+* @returns {string}
+*/
+function handle_issue_invite(issue_invite_request, issue_invite_response, lox_pub) {
+ let deferred5_0;
+ let deferred5_1;
+ try {
+ const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
+ const ptr0 = passStringToWasm0(issue_invite_request, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
+ const len0 = WASM_VECTOR_LEN;
+ const ptr1 = passStringToWasm0(issue_invite_response, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
+ const len1 = WASM_VECTOR_LEN;
+ const ptr2 = passStringToWasm0(lox_pub, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
+ const len2 = WASM_VECTOR_LEN;
+ wasm.handle_issue_invite(retptr, ptr0, len0, ptr1, len1, ptr2, len2);
+ var r0 = getInt32Memory0()[retptr / 4 + 0];
+ var r1 = getInt32Memory0()[retptr / 4 + 1];
+ var r2 = getInt32Memory0()[retptr / 4 + 2];
+ var r3 = getInt32Memory0()[retptr / 4 + 3];
+ var ptr4 = r0;
+ var len4 = r1;
+ if (r3) {
+ ptr4 = 0; len4 = 0;
+ throw takeObject(r2);
+ }
+ deferred5_0 = ptr4;
+ deferred5_1 = len4;
+ return getStringFromWasm0(ptr4, len4);
+ } finally {
+ wasm.__wbindgen_add_to_stack_pointer(16);
+ wasm.__wbindgen_free(deferred5_0, deferred5_1, 1);
+ }
+}
+
+/**
+* @param {string} invitation_cred
+* @returns {string}
+*/
+function prepare_invite(invitation_cred) {
+ let deferred3_0;
+ let deferred3_1;
+ try {
+ const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
+ const ptr0 = passStringToWasm0(invitation_cred, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
+ const len0 = WASM_VECTOR_LEN;
+ wasm.prepare_invite(retptr, ptr0, len0);
+ var r0 = getInt32Memory0()[retptr / 4 + 0];
+ var r1 = getInt32Memory0()[retptr / 4 + 1];
+ var r2 = getInt32Memory0()[retptr / 4 + 2];
+ var r3 = getInt32Memory0()[retptr / 4 + 3];
+ var ptr2 = r0;
+ var len2 = r1;
+ if (r3) {
+ ptr2 = 0; len2 = 0;
+ throw takeObject(r2);
+ }
+ deferred3_0 = ptr2;
+ deferred3_1 = len2;
+ return getStringFromWasm0(ptr2, len2);
+ } finally {
+ wasm.__wbindgen_add_to_stack_pointer(16);
+ wasm.__wbindgen_free(deferred3_0, deferred3_1, 1);
+ }
+}
+
+/**
+* @param {string} invitation
+* @param {string} lox_pub
+* @returns {string}
+*/
+function redeem_invite(invitation, lox_pub) {
+ let deferred4_0;
+ let deferred4_1;
+ try {
+ const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
+ const ptr0 = passStringToWasm0(invitation, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
+ const len0 = WASM_VECTOR_LEN;
+ const ptr1 = passStringToWasm0(lox_pub, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
+ const len1 = WASM_VECTOR_LEN;
+ wasm.redeem_invite(retptr, ptr0, len0, ptr1, len1);
+ var r0 = getInt32Memory0()[retptr / 4 + 0];
+ var r1 = getInt32Memory0()[retptr / 4 + 1];
+ var r2 = getInt32Memory0()[retptr / 4 + 2];
+ var r3 = getInt32Memory0()[retptr / 4 + 3];
+ var ptr3 = r0;
+ var len3 = r1;
+ if (r3) {
+ ptr3 = 0; len3 = 0;
+ throw takeObject(r2);
+ }
+ deferred4_0 = ptr3;
+ deferred4_1 = len3;
+ return getStringFromWasm0(ptr3, len3);
+ } finally {
+ wasm.__wbindgen_add_to_stack_pointer(16);
+ wasm.__wbindgen_free(deferred4_0, deferred4_1, 1);
+ }
+}
+
+/**
+* @param {string} redeem_invite_request
+* @param {string} redeem_invite_response
+* @param {string} lox_pub
+* @returns {string}
+*/
+function handle_redeem_invite(redeem_invite_request, redeem_invite_response, lox_pub) {
+ let deferred5_0;
+ let deferred5_1;
+ try {
+ const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
+ const ptr0 = passStringToWasm0(redeem_invite_request, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
+ const len0 = WASM_VECTOR_LEN;
+ const ptr1 = passStringToWasm0(redeem_invite_response, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
+ const len1 = WASM_VECTOR_LEN;
+ const ptr2 = passStringToWasm0(lox_pub, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
+ const len2 = WASM_VECTOR_LEN;
+ wasm.handle_redeem_invite(retptr, ptr0, len0, ptr1, len1, ptr2, len2);
+ var r0 = getInt32Memory0()[retptr / 4 + 0];
+ var r1 = getInt32Memory0()[retptr / 4 + 1];
+ var r2 = getInt32Memory0()[retptr / 4 + 2];
+ var r3 = getInt32Memory0()[retptr / 4 + 3];
+ var ptr4 = r0;
+ var len4 = r1;
+ if (r3) {
+ ptr4 = 0; len4 = 0;
+ throw takeObject(r2);
+ }
+ deferred5_0 = ptr4;
+ deferred5_1 = len4;
+ return getStringFromWasm0(ptr4, len4);
+ } finally {
+ wasm.__wbindgen_add_to_stack_pointer(16);
+ wasm.__wbindgen_free(deferred5_0, deferred5_1, 1);
+ }
+}
+
+/**
+* @param {string} lox_cred
+* @param {string} lox_pub
+* @returns {string}
+*/
+function check_blockage(lox_cred, lox_pub) {
+ let deferred4_0;
+ let deferred4_1;
+ try {
+ const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
+ const ptr0 = passStringToWasm0(lox_cred, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
+ const len0 = WASM_VECTOR_LEN;
+ const ptr1 = passStringToWasm0(lox_pub, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
+ const len1 = WASM_VECTOR_LEN;
+ wasm.check_blockage(retptr, ptr0, len0, ptr1, len1);
+ var r0 = getInt32Memory0()[retptr / 4 + 0];
+ var r1 = getInt32Memory0()[retptr / 4 + 1];
+ var r2 = getInt32Memory0()[retptr / 4 + 2];
+ var r3 = getInt32Memory0()[retptr / 4 + 3];
+ var ptr3 = r0;
+ var len3 = r1;
+ if (r3) {
+ ptr3 = 0; len3 = 0;
+ throw takeObject(r2);
+ }
+ deferred4_0 = ptr3;
+ deferred4_1 = len3;
+ return getStringFromWasm0(ptr3, len3);
+ } finally {
+ wasm.__wbindgen_add_to_stack_pointer(16);
+ wasm.__wbindgen_free(deferred4_0, deferred4_1, 1);
+ }
+}
+
+/**
+* @param {string} check_blockage_request
+* @param {string} check_blockage_response
+* @returns {string}
+*/
+function handle_check_blockage(check_blockage_request, check_blockage_response) {
+ let deferred4_0;
+ let deferred4_1;
+ try {
+ const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
+ const ptr0 = passStringToWasm0(check_blockage_request, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
+ const len0 = WASM_VECTOR_LEN;
+ const ptr1 = passStringToWasm0(check_blockage_response, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
+ const len1 = WASM_VECTOR_LEN;
+ wasm.handle_check_blockage(retptr, ptr0, len0, ptr1, len1);
+ var r0 = getInt32Memory0()[retptr / 4 + 0];
+ var r1 = getInt32Memory0()[retptr / 4 + 1];
+ var r2 = getInt32Memory0()[retptr / 4 + 2];
+ var r3 = getInt32Memory0()[retptr / 4 + 3];
+ var ptr3 = r0;
+ var len3 = r1;
+ if (r3) {
+ ptr3 = 0; len3 = 0;
+ throw takeObject(r2);
+ }
+ deferred4_0 = ptr3;
+ deferred4_1 = len3;
+ return getStringFromWasm0(ptr3, len3);
+ } finally {
+ wasm.__wbindgen_add_to_stack_pointer(16);
+ wasm.__wbindgen_free(deferred4_0, deferred4_1, 1);
+ }
+}
+
+/**
+* @param {string} lox_cred
+* @param {string} check_migration_cred
+* @param {string} lox_pub
+* @returns {string}
+*/
+function blockage_migration(lox_cred, check_migration_cred, lox_pub) {
+ let deferred5_0;
+ let deferred5_1;
+ try {
+ const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
+ const ptr0 = passStringToWasm0(lox_cred, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
+ const len0 = WASM_VECTOR_LEN;
+ const ptr1 = passStringToWasm0(check_migration_cred, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
+ const len1 = WASM_VECTOR_LEN;
+ const ptr2 = passStringToWasm0(lox_pub, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
+ const len2 = WASM_VECTOR_LEN;
+ wasm.blockage_migration(retptr, ptr0, len0, ptr1, len1, ptr2, len2);
+ var r0 = getInt32Memory0()[retptr / 4 + 0];
+ var r1 = getInt32Memory0()[retptr / 4 + 1];
+ var r2 = getInt32Memory0()[retptr / 4 + 2];
+ var r3 = getInt32Memory0()[retptr / 4 + 3];
+ var ptr4 = r0;
+ var len4 = r1;
+ if (r3) {
+ ptr4 = 0; len4 = 0;
+ throw takeObject(r2);
+ }
+ deferred5_0 = ptr4;
+ deferred5_1 = len4;
+ return getStringFromWasm0(ptr4, len4);
+ } finally {
+ wasm.__wbindgen_add_to_stack_pointer(16);
+ wasm.__wbindgen_free(deferred5_0, deferred5_1, 1);
+ }
+}
+
+/**
+* @param {string} blockage_migration_request
+* @param {string} blockage_migration_response
+* @param {string} lox_pub
+* @returns {string}
+*/
+function handle_blockage_migration(blockage_migration_request, blockage_migration_response, lox_pub) {
+ let deferred5_0;
+ let deferred5_1;
+ try {
+ const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
+ const ptr0 = passStringToWasm0(blockage_migration_request, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
+ const len0 = WASM_VECTOR_LEN;
+ const ptr1 = passStringToWasm0(blockage_migration_response, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
+ const len1 = WASM_VECTOR_LEN;
+ const ptr2 = passStringToWasm0(lox_pub, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
+ const len2 = WASM_VECTOR_LEN;
+ wasm.handle_blockage_migration(retptr, ptr0, len0, ptr1, len1, ptr2, len2);
+ var r0 = getInt32Memory0()[retptr / 4 + 0];
+ var r1 = getInt32Memory0()[retptr / 4 + 1];
+ var r2 = getInt32Memory0()[retptr / 4 + 2];
+ var r3 = getInt32Memory0()[retptr / 4 + 3];
+ var ptr4 = r0;
+ var len4 = r1;
+ if (r3) {
+ ptr4 = 0; len4 = 0;
+ throw takeObject(r2);
+ }
+ deferred5_0 = ptr4;
+ deferred5_1 = len4;
+ return getStringFromWasm0(ptr4, len4);
+ } finally {
+ wasm.__wbindgen_add_to_stack_pointer(16);
+ wasm.__wbindgen_free(deferred5_0, deferred5_1, 1);
+ }
+}
+
+/**
+* @param {string} lox_cred_str
+* @returns {string}
+*/
+function get_last_upgrade_time(lox_cred_str) {
+ let deferred3_0;
+ let deferred3_1;
+ try {
+ const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
+ const ptr0 = passStringToWasm0(lox_cred_str, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
+ const len0 = WASM_VECTOR_LEN;
+ wasm.get_last_upgrade_time(retptr, ptr0, len0);
+ var r0 = getInt32Memory0()[retptr / 4 + 0];
+ var r1 = getInt32Memory0()[retptr / 4 + 1];
+ var r2 = getInt32Memory0()[retptr / 4 + 2];
+ var r3 = getInt32Memory0()[retptr / 4 + 3];
+ var ptr2 = r0;
+ var len2 = r1;
+ if (r3) {
+ ptr2 = 0; len2 = 0;
+ throw takeObject(r2);
+ }
+ deferred3_0 = ptr2;
+ deferred3_1 = len2;
+ return getStringFromWasm0(ptr2, len2);
+ } finally {
+ wasm.__wbindgen_add_to_stack_pointer(16);
+ wasm.__wbindgen_free(deferred3_0, deferred3_1, 1);
+ }
+}
+
+/**
+* @param {string} lox_cred_str
+* @returns {string}
+*/
+function get_trust_level(lox_cred_str) {
+ let deferred3_0;
+ let deferred3_1;
+ try {
+ const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
+ const ptr0 = passStringToWasm0(lox_cred_str, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
+ const len0 = WASM_VECTOR_LEN;
+ wasm.get_trust_level(retptr, ptr0, len0);
+ var r0 = getInt32Memory0()[retptr / 4 + 0];
+ var r1 = getInt32Memory0()[retptr / 4 + 1];
+ var r2 = getInt32Memory0()[retptr / 4 + 2];
+ var r3 = getInt32Memory0()[retptr / 4 + 3];
+ var ptr2 = r0;
+ var len2 = r1;
+ if (r3) {
+ ptr2 = 0; len2 = 0;
+ throw takeObject(r2);
+ }
+ deferred3_0 = ptr2;
+ deferred3_1 = len2;
+ return getStringFromWasm0(ptr2, len2);
+ } finally {
+ wasm.__wbindgen_add_to_stack_pointer(16);
+ wasm.__wbindgen_free(deferred3_0, deferred3_1, 1);
+ }
+}
+
+/**
+* @param {string} lox_cred_str
+* @returns {string}
+*/
+function get_invites_remaining(lox_cred_str) {
+ let deferred3_0;
+ let deferred3_1;
+ try {
+ const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
+ const ptr0 = passStringToWasm0(lox_cred_str, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
+ const len0 = WASM_VECTOR_LEN;
+ wasm.get_invites_remaining(retptr, ptr0, len0);
+ var r0 = getInt32Memory0()[retptr / 4 + 0];
+ var r1 = getInt32Memory0()[retptr / 4 + 1];
+ var r2 = getInt32Memory0()[retptr / 4 + 2];
+ var r3 = getInt32Memory0()[retptr / 4 + 3];
+ var ptr2 = r0;
+ var len2 = r1;
+ if (r3) {
+ ptr2 = 0; len2 = 0;
+ throw takeObject(r2);
+ }
+ deferred3_0 = ptr2;
+ deferred3_1 = len2;
+ return getStringFromWasm0(ptr2, len2);
+ } finally {
+ wasm.__wbindgen_add_to_stack_pointer(16);
+ wasm.__wbindgen_free(deferred3_0, deferred3_1, 1);
+ }
+}
+
+/**
+* @param {string} lox_cred_str
+* @returns {string}
+*/
+function get_issued_invite_expiry(lox_cred_str) {
+ let deferred3_0;
+ let deferred3_1;
+ try {
+ const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
+ const ptr0 = passStringToWasm0(lox_cred_str, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
+ const len0 = WASM_VECTOR_LEN;
+ wasm.get_issued_invite_expiry(retptr, ptr0, len0);
+ var r0 = getInt32Memory0()[retptr / 4 + 0];
+ var r1 = getInt32Memory0()[retptr / 4 + 1];
+ var r2 = getInt32Memory0()[retptr / 4 + 2];
+ var r3 = getInt32Memory0()[retptr / 4 + 3];
+ var ptr2 = r0;
+ var len2 = r1;
+ if (r3) {
+ ptr2 = 0; len2 = 0;
+ throw takeObject(r2);
+ }
+ deferred3_0 = ptr2;
+ deferred3_1 = len2;
+ return getStringFromWasm0(ptr2, len2);
+ } finally {
+ wasm.__wbindgen_add_to_stack_pointer(16);
+ wasm.__wbindgen_free(deferred3_0, deferred3_1, 1);
+ }
+}
+
+/**
+* @param {string} invite_cred_str
+* @returns {string}
+*/
+function get_received_invite_expiry(invite_cred_str) {
+ let deferred3_0;
+ let deferred3_1;
+ try {
+ const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
+ const ptr0 = passStringToWasm0(invite_cred_str, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
+ const len0 = WASM_VECTOR_LEN;
+ wasm.get_received_invite_expiry(retptr, ptr0, len0);
+ var r0 = getInt32Memory0()[retptr / 4 + 0];
+ var r1 = getInt32Memory0()[retptr / 4 + 1];
+ var r2 = getInt32Memory0()[retptr / 4 + 2];
+ var r3 = getInt32Memory0()[retptr / 4 + 3];
+ var ptr2 = r0;
+ var len2 = r1;
+ if (r3) {
+ ptr2 = 0; len2 = 0;
+ throw takeObject(r2);
+ }
+ deferred3_0 = ptr2;
+ deferred3_1 = len2;
+ return getStringFromWasm0(ptr2, len2);
+ } finally {
+ wasm.__wbindgen_add_to_stack_pointer(16);
+ wasm.__wbindgen_free(deferred3_0, deferred3_1, 1);
+ }
+}
+
+/**
+* @param {string} lox_cred_str
+* @param {string} encrypted_table
+* @returns {string}
+*/
+function get_bridgelines_from_bucket(lox_cred_str, encrypted_table) {
+ let deferred4_0;
+ let deferred4_1;
+ try {
+ const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
+ const ptr0 = passStringToWasm0(lox_cred_str, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
+ const len0 = WASM_VECTOR_LEN;
+ const ptr1 = passStringToWasm0(encrypted_table, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
+ const len1 = WASM_VECTOR_LEN;
+ wasm.get_bridgelines_from_bucket(retptr, ptr0, len0, ptr1, len1);
+ var r0 = getInt32Memory0()[retptr / 4 + 0];
+ var r1 = getInt32Memory0()[retptr / 4 + 1];
+ var r2 = getInt32Memory0()[retptr / 4 + 2];
+ var r3 = getInt32Memory0()[retptr / 4 + 3];
+ var ptr3 = r0;
+ var len3 = r1;
+ if (r3) {
+ ptr3 = 0; len3 = 0;
+ throw takeObject(r2);
+ }
+ deferred4_0 = ptr3;
+ deferred4_1 = len3;
+ return getStringFromWasm0(ptr3, len3);
+ } finally {
+ wasm.__wbindgen_add_to_stack_pointer(16);
+ wasm.__wbindgen_free(deferred4_0, deferred4_1, 1);
+ }
+}
+
+/**
+* @param {string} unspecified_invitation_str
+* @returns {boolean}
+*/
+function invitation_is_trusted(unspecified_invitation_str) {
+ try {
+ const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
+ const ptr0 = passStringToWasm0(unspecified_invitation_str, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
+ const len0 = WASM_VECTOR_LEN;
+ wasm.invitation_is_trusted(retptr, ptr0, len0);
+ var r0 = getInt32Memory0()[retptr / 4 + 0];
+ var r1 = getInt32Memory0()[retptr / 4 + 1];
+ var r2 = getInt32Memory0()[retptr / 4 + 2];
+ if (r2) {
+ throw takeObject(r1);
+ }
+ return r0 !== 0;
+ } finally {
+ wasm.__wbindgen_add_to_stack_pointer(16);
+ }
+}
+
+/**
+* @param {string} constants_str
+* @param {string} lox_cred_str
+* @returns {string}
+*/
+function get_next_unlock(constants_str, lox_cred_str) {
+ let deferred4_0;
+ let deferred4_1;
+ try {
+ const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
+ const ptr0 = passStringToWasm0(constants_str, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
+ const len0 = WASM_VECTOR_LEN;
+ const ptr1 = passStringToWasm0(lox_cred_str, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
+ const len1 = WASM_VECTOR_LEN;
+ wasm.get_next_unlock(retptr, ptr0, len0, ptr1, len1);
+ var r0 = getInt32Memory0()[retptr / 4 + 0];
+ var r1 = getInt32Memory0()[retptr / 4 + 1];
+ var r2 = getInt32Memory0()[retptr / 4 + 2];
+ var r3 = getInt32Memory0()[retptr / 4 + 3];
+ var ptr3 = r0;
+ var len3 = r1;
+ if (r3) {
+ ptr3 = 0; len3 = 0;
+ throw takeObject(r2);
+ }
+ deferred4_0 = ptr3;
+ deferred4_1 = len3;
+ return getStringFromWasm0(ptr3, len3);
+ } finally {
+ wasm.__wbindgen_add_to_stack_pointer(16);
+ wasm.__wbindgen_free(deferred4_0, deferred4_1, 1);
+ }
+}
+
+function handleError(f, args) {
+ try {
+ return f.apply(this, args);
+ } catch (e) {
+ wasm.__wbindgen_exn_store(addHeapObject(e));
+ }
+}
+
+async function __wbg_load(module, imports) {
+ if (typeof Response === 'function' && module instanceof Response) {
+ if (typeof WebAssembly.instantiateStreaming === 'function') {
+ try {
+ return await WebAssembly.instantiateStreaming(module, imports);
+
+ } catch (e) {
+ if (module.headers.get('Content-Type') != 'application/wasm') {
+ console.warn("`WebAssembly.instantiateStreaming` failed because your server does not serve wasm with `application/wasm` MIME type. Falling back to `WebAssembly.instantiate` which is slower. Original error:\n", e);
+
+ } else {
+ throw e;
+ }
+ }
+ }
+
+ const bytes = await module.arrayBuffer();
+ return await WebAssembly.instantiate(bytes, imports);
+
+ } else {
+ const instance = await WebAssembly.instantiate(module, imports);
+
+ if (instance instanceof WebAssembly.Instance) {
+ return { instance, module };
+
+ } else {
+ return instance;
+ }
+ }
+}
+
+function __wbg_get_imports(window) {
+ const imports = {};
+ imports.wbg = {};
+ imports.wbg.__wbg_new0_622c21a64f3d83ea = function() {
+ const ret = new Date();
+ return addHeapObject(ret);
+ };
+ imports.wbg.__wbg_getTime_9272be78826033e1 = function(arg0) {
+ const ret = getObject(arg0).getTime();
+ return ret;
+ };
+ imports.wbg.__wbindgen_object_drop_ref = function(arg0) {
+ takeObject(arg0);
+ };
+ imports.wbg.__wbg_log_9b9925d843c39805 = function(arg0, arg1) {
+ console.log(getStringFromWasm0(arg0, arg1));
+ };
+ imports.wbg.__wbindgen_string_new = function(arg0, arg1) {
+ const ret = getStringFromWasm0(arg0, arg1);
+ return addHeapObject(ret);
+ };
+ imports.wbg.__wbg_new_abda76e883ba8a5f = function() {
+ const ret = new Error();
+ return addHeapObject(ret);
+ };
+ imports.wbg.__wbg_stack_658279fe44541cf6 = function(arg0, arg1) {
+ const ret = getObject(arg1).stack;
+ const ptr1 = passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
+ const len1 = WASM_VECTOR_LEN;
+ getInt32Memory0()[arg0 / 4 + 1] = len1;
+ getInt32Memory0()[arg0 / 4 + 0] = ptr1;
+ };
+ imports.wbg.__wbg_error_f851667af71bcfc6 = function(arg0, arg1) {
+ let deferred0_0;
+ let deferred0_1;
+ try {
+ deferred0_0 = arg0;
+ deferred0_1 = arg1;
+ console.error(getStringFromWasm0(arg0, arg1));
+ } finally {
+ wasm.__wbindgen_free(deferred0_0, deferred0_1, 1);
+ }
+ };
+ imports.wbg.__wbindgen_object_clone_ref = function(arg0) {
+ const ret = getObject(arg0);
+ return addHeapObject(ret);
+ };
+ imports.wbg.__wbg_crypto_c48a774b022d20ac = function(arg0) {
+ const ret = getObject(arg0).crypto;
+ return addHeapObject(ret);
+ };
+ imports.wbg.__wbindgen_is_object = function(arg0) {
+ const val = getObject(arg0);
+ const ret = typeof(val) === 'object' && val !== null;
+ return ret;
+ };
+ imports.wbg.__wbg_process_298734cf255a885d = function(arg0) {
+ const ret = getObject(arg0).process;
+ return addHeapObject(ret);
+ };
+ imports.wbg.__wbg_versions_e2e78e134e3e5d01 = function(arg0) {
+ const ret = getObject(arg0).versions;
+ return addHeapObject(ret);
+ };
+ imports.wbg.__wbg_node_1cd7a5d853dbea79 = function(arg0) {
+ const ret = getObject(arg0).node;
+ return addHeapObject(ret);
+ };
+ imports.wbg.__wbindgen_is_string = function(arg0) {
+ const ret = typeof(getObject(arg0)) === 'string';
+ return ret;
+ };
+ imports.wbg.__wbg_require_8f08ceecec0f4fee = function() { return handleError(function () {
+ const ret = module.require;
+ return addHeapObject(ret);
+ }, arguments) };
+ imports.wbg.__wbindgen_is_function = function(arg0) {
+ const ret = typeof(getObject(arg0)) === 'function';
+ return ret;
+ };
+ imports.wbg.__wbg_call_5da1969d7cd31ccd = function() { return handleError(function (arg0, arg1, arg2) {
+ const ret = getObject(arg0).call(getObject(arg1), getObject(arg2));
+ return addHeapObject(ret);
+ }, arguments) };
+ imports.wbg.__wbg_msCrypto_bcb970640f50a1e8 = function(arg0) {
+ const ret = getObject(arg0).msCrypto;
+ return addHeapObject(ret);
+ };
+ imports.wbg.__wbg_newwithlength_6c2df9e2f3028c43 = function(arg0) {
+ const ret = new Uint8Array(arg0 >>> 0);
+ return addHeapObject(ret);
+ };
+ imports.wbg.__wbg_self_f0e34d89f33b99fd = function() { return handleError(function () {
+ const ret = window;
+ return addHeapObject(ret);
+ }, arguments) };
+ imports.wbg.__wbg_window_d3b084224f4774d7 = function() { return handleError(function () {
+ const ret = window.window;
+ return addHeapObject(ret);
+ }, arguments) };
+ imports.wbg.__wbg_globalThis_9caa27ff917c6860 = function() { return handleError(function () {
+ const ret = globalThis.globalThis;
+ return addHeapObject(ret);
+ }, arguments) };
+ imports.wbg.__wbg_global_35dfdd59a4da3e74 = function() { return handleError(function () {
+ const ret = global.global;
+ return addHeapObject(ret);
+ }, arguments) };
+ imports.wbg.__wbindgen_is_undefined = function(arg0) {
+ const ret = getObject(arg0) === undefined;
+ return ret;
+ };
+ imports.wbg.__wbg_newnoargs_c62ea9419c21fbac = function(arg0, arg1) {
+ const ret = new Function(getStringFromWasm0(arg0, arg1));
+ return addHeapObject(ret);
+ };
+ imports.wbg.__wbg_call_90c26b09837aba1c = function() { return handleError(function (arg0, arg1) {
+ const ret = getObject(arg0).call(getObject(arg1));
+ return addHeapObject(ret);
+ }, arguments) };
+ imports.wbg.__wbindgen_memory = function() {
+ const ret = wasm.memory;
+ return addHeapObject(ret);
+ };
+ imports.wbg.__wbg_buffer_a448f833075b71ba = function(arg0) {
+ const ret = getObject(arg0).buffer;
+ return addHeapObject(ret);
+ };
+ imports.wbg.__wbg_newwithbyteoffsetandlength_d0482f893617af71 = function(arg0, arg1, arg2) {
+ const ret = new Uint8Array(getObject(arg0), arg1 >>> 0, arg2 >>> 0);
+ return addHeapObject(ret);
+ };
+ imports.wbg.__wbg_randomFillSync_dc1e9a60c158336d = function() { return handleError(function (arg0, arg1) {
+ getObject(arg0).randomFillSync(takeObject(arg1));
+ }, arguments) };
+ imports.wbg.__wbg_subarray_2e940e41c0f5a1d9 = function(arg0, arg1, arg2) {
+ const ret = getObject(arg0).subarray(arg1 >>> 0, arg2 >>> 0);
+ return addHeapObject(ret);
+ };
+ imports.wbg.__wbg_getRandomValues_37fa2ca9e4e07fab = function() { return handleError(function (arg0, arg1) {
+ getObject(arg0).getRandomValues(getObject(arg1));
+ }, arguments) };
+ imports.wbg.__wbg_new_8f67e318f15d7254 = function(arg0) {
+ const ret = new Uint8Array(getObject(arg0));
+ return addHeapObject(ret);
+ };
+ imports.wbg.__wbg_set_2357bf09366ee480 = function(arg0, arg1, arg2) {
+ getObject(arg0).set(getObject(arg1), arg2 >>> 0);
+ };
+ imports.wbg.__wbindgen_throw = function(arg0, arg1) {
+ throw new Error(getStringFromWasm0(arg0, arg1));
+ };
+
+ return imports;
+}
+
+function __wbg_init_memory(imports, maybe_memory) {
+
+}
+
+function __wbg_finalize_init(instance, module) {
+ wasm = instance.exports;
+ init.__wbindgen_wasm_module = module;
+ cachedInt32Memory0 = null;
+ cachedUint8Memory0 = null;
+
+
+ return wasm;
+}
+
+function initSync(module, window) {
+ if (wasm !== undefined) return wasm;
+
+ const imports = __wbg_get_imports(window);
+
+ __wbg_init_memory(imports);
+
+ if (!(module instanceof WebAssembly.Module)) {
+ module = new WebAssembly.Module(module);
+ }
+
+ const instance = new WebAssembly.Instance(module, imports);
+
+ return __wbg_finalize_init(instance, module);
+}
+
+async function init(window, input) {
+ if (wasm !== undefined) return wasm;
+
+ if (typeof input === 'undefined') {{
+ input = "chrome://global/content/lox/lox_wasm_bg.wasm";
+ }}
+ const imports = __wbg_get_imports(window);
+
+ if (typeof input === 'string' || (typeof Request === 'function' && input instanceof Request) || (typeof URL === 'function' && input instanceof URL)) {
+ input = fetch(input);
+ }
+
+ __wbg_init_memory(imports);
+
+ const { instance, module } = await __wbg_load(await input, imports);
+
+ return __wbg_finalize_init(instance, module);
+}
+
=====================================
toolkit/components/lox/moz.build
=====================================
@@ -0,0 +1,7 @@
+EXTRA_JS_MODULES += [
+ "Lox.sys.mjs",
+ # Let's keep the old jsm format until wasm-bindgen is updated
+ "lox_wasm.jsm",
+]
+
+JAR_MANIFESTS += ["jar.mn"]
=====================================
toolkit/components/moz.build
=====================================
@@ -46,6 +46,7 @@ DIRS += [
"httpsonlyerror",
"jsoncpp/src/lib_json",
"kvstore",
+ "lox",
"mediasniffer",
"mozintl",
"mozprotocol",
=====================================
toolkit/components/tor-launcher/TorStartupService.sys.mjs
=====================================
@@ -54,5 +54,6 @@ export class TorStartupService {
lazy.TorProviderBuilder.uninit();
lazy.TorLauncherUtil.cleanupTempDirectories();
+ lazy.TorSettings.uninit();
}
}
=====================================
toolkit/modules/TorSettings.sys.mjs
=====================================
@@ -8,6 +8,7 @@ ChromeUtils.defineESModuleGetters(lazy, {
TorLauncherUtil: "resource://gre/modules/TorLauncherUtil.sys.mjs",
TorProviderBuilder: "resource://gre/modules/TorProviderBuilder.sys.mjs",
TorProviderTopics: "resource://gre/modules/TorProviderBuilder.sys.mjs",
+ Lox: "resource://gre/modules/Lox.sys.mjs",
});
ChromeUtils.defineLazyGetter(lazy, "logger", () => {
@@ -40,6 +41,8 @@ const TorSettingsPrefs = Object.freeze({
enabled: "torbrowser.settings.bridges.enabled",
/* int: See TorBridgeSource */
source: "torbrowser.settings.bridges.source",
+ /* string: output of crypto.randomUUID() */
+ lox_id: "torbrowser.settings.bridges.lox_id",
/* string: obfs4|meek-azure|snowflake|etc */
builtin_type: "torbrowser.settings.bridges.builtin_type",
/* preference branch: each child branch should be a bridge string */
@@ -86,6 +89,7 @@ export const TorBridgeSource = Object.freeze({
BuiltIn: 0,
BridgeDB: 1,
UserProvided: 2,
+ Lox: 3,
});
export const TorProxyType = Object.freeze({
@@ -159,6 +163,7 @@ class TorSettingsImpl {
bridges: {
enabled: false,
source: TorBridgeSource.Invalid,
+ lox_id: "",
builtin_type: "",
bridge_strings: [],
},
@@ -292,6 +297,20 @@ class TorSettingsImpl {
this.bridges.source = TorBridgeSource.Invalid;
},
},
+ /**
+ * The lox id is used with the Lox "source", and remains set with the stored value when
+ * other sources are used.
+ *
+ * @type {string}
+ */
+ lox_id: {
+ callback: (val, addError) => {
+ if (!val) {
+ return;
+ }
+ this.bridges.bridge_strings = lazy.Lox.getBridges(val);
+ },
+ },
});
this.#addProperties("proxy", {
enabled: {},
@@ -379,6 +398,9 @@ class TorSettingsImpl {
if (this.bridges.source !== TorBridgeSource.BuiltIn) {
this.bridges.builtin_type = "";
}
+ if (this.bridges.source !== TorBridgeSource.Lox) {
+ this.bridges.lox_id = "";
+ }
if (!this.proxy.enabled) {
this.proxy.type = TorProxyType.Invalid;
this.proxy.address = "";
@@ -639,6 +661,14 @@ class TorSettingsImpl {
lazy.logger.error("Could not load the built-in PT config.", e);
}
+ // Initialize this before loading from prefs because we need Lox initialized before
+ // any calls to Lox.getBridges()
+ try {
+ await lazy.Lox.init();
+ } catch (e) {
+ lazy.logger.error("Could not initialize Lox.", e.type);
+ }
+
// TODO: We could use a shared promise, and wait for it to be fullfilled
// instead of Service.obs.
if (lazy.TorLauncherUtil.shouldStartAndOwnTor) {
@@ -668,6 +698,13 @@ class TorSettingsImpl {
}
}
+ /**
+ * Unload or uninit our settings, and unregister observers.
+ */
+ async uninit() {
+ await lazy.Lox.uninit();
+ }
+
/**
* Check whether the object has been successfully initialized, and throw if
* it has not.
@@ -738,6 +775,10 @@ class TorSettingsImpl {
TorSettingsPrefs.bridges.source,
TorBridgeSource.Invalid
);
+ this.bridges.lox_id = Services.prefs.getStringPref(
+ TorSettingsPrefs.bridges.lox_id,
+ ""
+ );
if (this.bridges.source == TorBridgeSource.BuiltIn) {
this.bridges.builtin_type = Services.prefs.getStringPref(
TorSettingsPrefs.bridges.builtin_type,
@@ -823,6 +864,10 @@ class TorSettingsImpl {
TorSettingsPrefs.bridges.builtin_type,
this.bridges.builtin_type
);
+ Services.prefs.setStringPref(
+ TorSettingsPrefs.bridges.lox_id,
+ this.bridges.lox_id
+ );
// erase existing bridge strings
const bridgeBranchPrefs = Services.prefs
.getBranch(TorSettingsPrefs.bridges.bridge_strings)
@@ -1013,6 +1058,9 @@ class TorSettingsImpl {
case TorBridgeSource.BuiltIn:
this.bridges.builtin_type = settings.bridges.builtin_type;
break;
+ case TorBridgeSource.Lox:
+ this.bridges.lox_id = settings.bridges.lox_id;
+ break;
case TorBridgeSource.Invalid:
break;
}
View it on GitLab: https://gitlab.torproject.org/tpo/applications/tor-browser/-/compare/a48e43…
--
View it on GitLab: https://gitlab.torproject.org/tpo/applications/tor-browser/-/compare/a48e43…
You're receiving this email because of your account on gitlab.torproject.org.
[View Less]
1
0

[Git][tpo/applications/tor-browser][tor-browser-115.7.0esr-13.5-1] 2 commits: fixup! Bug 40597: Implement TorSettings module
by richard (@richard) 26 Jan '24
by richard (@richard) 26 Jan '24
26 Jan '24
richard pushed to branch tor-browser-115.7.0esr-13.5-1 at The Tor Project / Applications / Tor Browser
Commits:
bb028644 by Pier Angelo Vendrame at 2024-01-26T11:31:15+01:00
fixup! Bug 40597: Implement TorSettings module
Bug 42384: Use TorSettings's initialization promise to handle race
conditions
We now have a race condition for which the notification about
TorSettings being ready is sent before TorConnect can observe this
topic.
A while ago, we introduced an initialization promise …
[View More]to TorSettings,
therefore we can use it instead of Service.obs and avoid this race
condition.
Also, fixed quicksettings ignored in TorSettings.setSettings.
- - - - -
a48e4389 by Pier Angelo Vendrame at 2024-01-26T11:35:10+01:00
fixup! Bug 42247: Android helpers for the TorProvider
Update the cached mSettings whenever someone one the GeckoView side
changes any TorSettings settings.
- - - - -
4 changed files:
- mobile/android/geckoview/src/main/java/org/mozilla/geckoview/TorIntegrationAndroid.java
- toolkit/modules/TorAndroidIntegration.sys.mjs
- toolkit/modules/TorConnect.sys.mjs
- toolkit/modules/TorSettings.sys.mjs
Changes:
=====================================
mobile/android/geckoview/src/main/java/org/mozilla/geckoview/TorIntegrationAndroid.java
=====================================
@@ -47,6 +47,8 @@ public class TorIntegrationAndroid implements BundleEventListener {
private static final String EVENT_BOOTSTRAP_COMPLETE = "GeckoView:Tor:BootstrapComplete";
private static final String EVENT_BOOTSTRAP_ERROR = "GeckoView:Tor:BootstrapError";
private static final String EVENT_SETTINGS_OPEN = "GeckoView:Tor:OpenSettings";
+ private static final String EVENT_SETTINGS_READY = "GeckoView:Tor:SettingsReady";
+ private static final String EVENT_SETTINGS_CHANGED = "GeckoView:Tor:SettingsChanged";
// Events we emit
private static final String EVENT_SETTINGS_GET = "GeckoView:Tor:SettingsGet";
@@ -57,7 +59,6 @@ public class TorIntegrationAndroid implements BundleEventListener {
private static final String EVENT_BOOTSTRAP_BEGIN_AUTO = "GeckoView:Tor:BootstrapBeginAuto";
private static final String EVENT_BOOTSTRAP_CANCEL = "GeckoView:Tor:BootstrapCancel";
private static final String EVENT_BOOTSTRAP_GET_STATE = "GeckoView:Tor:BootstrapGetState";
- private static final String EVENT_SETTINGS_READY = "GeckoView:Tor:SettingsReady";
private static final String CONTROL_PORT_FILE = "/control-ipc";
private static final String SOCKS_FILE = "/socks-ipc";
@@ -112,6 +113,7 @@ public class TorIntegrationAndroid implements BundleEventListener {
EVENT_MEEK_START,
EVENT_MEEK_STOP,
EVENT_SETTINGS_READY,
+ EVENT_SETTINGS_CHANGED,
EVENT_BOOTSTRAP_STATE_CHANGED,
EVENT_BOOTSTRAP_PROGRESS,
EVENT_BOOTSTRAP_COMPLETE,
@@ -136,6 +138,14 @@ public class TorIntegrationAndroid implements BundleEventListener {
} catch(Exception e) {
Log.e(TAG, "SettingsLoader error: "+ e.toString());
}
+ } else if (EVENT_SETTINGS_CHANGED.equals(event)) {
+ GeckoBundle newSettings = message.getBundle("settings");
+ if (newSettings != null) {
+ // TODO: Should we notify listeners?
+ mSettings = new TorSettings(newSettings);
+ } else {
+ Log.w(TAG, "Ignoring a settings changed event that did not have the new settings.");
+ }
} else if (EVENT_BOOTSTRAP_STATE_CHANGED.equals(event)) {
String state = message.getString("state");
for (BootstrapStateChangeListener listener: mBootstrapStateListeners) {
=====================================
toolkit/modules/TorAndroidIntegration.sys.mjs
=====================================
@@ -124,6 +124,15 @@ class TorAndroidIntegrationImpl {
settings: lazy.TorSettings.getSettings(),
});
break;
+ case lazy.TorSettingsTopics.SettingsChanged:
+ // For Android we push also the settings object to avoid a round trip on
+ // the event dispatcher.
+ lazy.EventDispatcher.instance.sendRequest({
+ type: EmittedEvents.settingsChanged,
+ changes: subj.wrappedJSObject.changes ?? [],
+ settings: lazy.TorSettings.getSettings(),
+ });
+ break;
}
}
=====================================
toolkit/modules/TorConnect.sys.mjs
=====================================
@@ -878,10 +878,11 @@ export const TorConnect = (() => {
console.log(`TorConnect: Observing topic '${addTopic}'`);
};
+ TorSettings.initializedPromise.then(() => this._settingsInitialized());
+
// register the Tor topics we always care about
observeTopic(TorTopics.ProcessExited);
observeTopic(TorTopics.LogHasWarnOrErr);
- observeTopic(TorSettingsTopics.Ready);
}
},
@@ -889,29 +890,6 @@ export const TorConnect = (() => {
console.log(`TorConnect: Observed ${topic}`);
switch (topic) {
- /* We need to wait until TorSettings have been loaded and applied before we can Quickstart */
- case TorSettingsTopics.Ready: {
- // tor-browser#41907: This is only a workaround to avoid users being
- // bounced back to the initial panel without any explanation.
- // Longer term we should disable the clickable elements, or find a UX
- // to prevent this from happening (e.g., allow buttons to be clicked,
- // but show an intermediate starting state, or a message that tor is
- // starting while the butons are disabled, etc...).
- if (this.state !== TorConnectState.Initial) {
- console.warn(
- "TorConnect: Seen the torsettings:ready after the state has already changed, ignoring the notification."
- );
- break;
- }
- if (this.shouldQuickStart) {
- // Quickstart
- this._changeState(TorConnectState.Bootstrapping);
- } else {
- // Configuring
- this._changeState(TorConnectState.Configuring);
- }
- break;
- }
case TorTopics.LogHasWarnOrErr: {
this._logHasWarningOrError = true;
break;
@@ -941,6 +919,28 @@ export const TorConnect = (() => {
}
},
+ _settingsInitialized() {
+ // tor-browser#41907: This is only a workaround to avoid users being
+ // bounced back to the initial panel without any explanation.
+ // Longer term we should disable the clickable elements, or find a UX
+ // to prevent this from happening (e.g., allow buttons to be clicked,
+ // but show an intermediate starting state, or a message that tor is
+ // starting while the butons are disabled, etc...).
+ if (this.state !== TorConnectState.Initial) {
+ console.warn(
+ "TorConnect: Seen the torsettings:ready after the state has already changed, ignoring the notification."
+ );
+ return;
+ }
+ if (this.shouldQuickStart) {
+ // Quickstart
+ this._changeState(TorConnectState.Bootstrapping);
+ } else {
+ // Configuring
+ this._changeState(TorConnectState.Configuring);
+ }
+ },
+
/*
Various getters
*/
=====================================
toolkit/modules/TorSettings.sys.mjs
=====================================
@@ -992,6 +992,10 @@ class TorSettingsImpl {
// Hold off on lots of notifications until all settings are changed.
this.freezeNotifications();
try {
+ if ("quickstart" in settings) {
+ this.quickstart.enabled = !!settings.quickstart.enabled;
+ }
+
if ("bridges" in settings) {
this.bridges.enabled = !!settings.bridges.enabled;
// Currently, disabling bridges in the UI does not remove the lines,
View it on GitLab: https://gitlab.torproject.org/tpo/applications/tor-browser/-/compare/db59cb…
--
View it on GitLab: https://gitlab.torproject.org/tpo/applications/tor-browser/-/compare/db59cb…
You're receiving this email because of your account on gitlab.torproject.org.
[View Less]
1
0

[Git][tpo/applications/firefox-android][firefox-android-115.2.1-13.5-1] fixup! Add Tor integration and UI
by Dan Ballard (@dan) 26 Jan '24
by Dan Ballard (@dan) 26 Jan '24
26 Jan '24
Dan Ballard pushed to branch firefox-android-115.2.1-13.5-1 at The Tor Project / Applications / firefox-android
Commits:
6d0a6453 by Dan Ballard at 2024-01-25T16:15:45-08:00
fixup! Add Tor integration and UI
Bug 42252: Make TorController and interface and add a Geckoview implementation
- - - - -
4 changed files:
- fenix/app/src/main/java/org/mozilla/fenix/components/Components.kt
- fenix/app/src/main/java/org/mozilla/fenix/tor/TorController.kt
- + fenix/app/src/main/java/org/mozilla/…
[View More]fenix/tor/TorControllerGV.kt
- + fenix/app/src/main/java/org/mozilla/fenix/tor/TorControllerTAS.kt
Changes:
=====================================
fenix/app/src/main/java/org/mozilla/fenix/components/Components.kt
=====================================
@@ -43,7 +43,8 @@ import org.mozilla.fenix.perf.StartupActivityLog
import org.mozilla.fenix.perf.StartupStateProvider
import org.mozilla.fenix.perf.StrictModeManager
import org.mozilla.fenix.perf.lazyMonitored
-import org.mozilla.fenix.tor.TorController
+import org.mozilla.fenix.tor.TorControllerGV
+import org.mozilla.fenix.tor.TorControllerTAS
import org.mozilla.fenix.utils.ClipboardHandler
import org.mozilla.fenix.utils.Settings
import org.mozilla.fenix.wifi.WifiConnectionMonitor
@@ -201,7 +202,7 @@ class Components(private val context: Context) {
),
)
}
- val torController by lazyMonitored { TorController(context) }
+ val torController by lazyMonitored { if (settings.useNewBootstrap) TorControllerGV(context) else TorControllerTAS(context) }
}
/**
=====================================
fenix/app/src/main/java/org/mozilla/fenix/tor/TorController.kt
=====================================
@@ -4,22 +4,7 @@
package org.mozilla.fenix.tor
-import android.content.BroadcastReceiver
-import android.content.Context
-import android.content.Intent
-import android.content.IntentFilter
import androidx.lifecycle.LifecycleCoroutineScope
-import androidx.localbroadcastmanager.content.LocalBroadcastManager
-
-import kotlinx.coroutines.channels.Channel
-import kotlinx.coroutines.launch
-import kotlinx.coroutines.withTimeoutOrNull
-
-import org.mozilla.fenix.BuildConfig
-
-import org.torproject.android.service.TorService
-import org.torproject.android.service.TorServiceConstants
-import org.torproject.android.service.util.Prefs
interface TorEvents {
fun onTorConnecting()
@@ -28,347 +13,59 @@ interface TorEvents {
fun onTorStopped()
}
-private enum class TorStatus {
- OFF,
- STARTING,
- ON,
- STOPPING,
- UNKNOWN;
+internal enum class TorStatus(val status: String) {
+ OFF("OFF"),
+ STARTING("STARTING"),
+ ON("ON"),
+ STOPPING("STOPPING"),
+ UNKNOWN("UNKNOWN");
- fun getStateFromString(status: String): TorStatus {
- return when (status) {
- TorServiceConstants.STATUS_ON -> ON
- TorServiceConstants.STATUS_STARTING -> STARTING
- TorServiceConstants.STATUS_STOPPING -> STOPPING
- TorServiceConstants.STATUS_OFF -> OFF
- else -> UNKNOWN
+ companion object {
+ fun fromString(status: String): TorStatus {
+ return when (status) {
+ "ON" -> ON
+ "STARTING" -> STARTING
+ "STOPPING" -> STOPPING
+ "OFF" -> OFF
+ else -> UNKNOWN
+ }
}
}
fun isOff() = this == OFF
fun isOn() = this == ON
fun isStarting() = this == STARTING
- fun isStarted() = ((this == TorStatus.STARTING) || (this == TorStatus.ON))
+ fun isStarted() = ((this == STARTING) || (this == ON))
fun isStopping() = this == STOPPING
fun isUnknown() = this == UNKNOWN
}
-@SuppressWarnings("TooManyFunctions")
-class TorController(
- private val context: Context
-) : TorEvents {
-
- private val lbm: LocalBroadcastManager = LocalBroadcastManager.getInstance(context)
- private val entries = mutableListOf<Pair<String?, String?>>()
- val logEntries get() = entries
-
- private var torListeners = mutableListOf<TorEvents>()
-
- private var pendingRegisterChangeList = mutableListOf<Pair<TorEvents, Boolean>>()
- private var lockTorListenersMutation = false
-
- private var lastKnownStatus = TorStatus.OFF
- private var wasTorBootstrapped = false
- private var isTorRestarting = false
-
- // This may be a lie
- private var isTorBootstrapped = false
- get() = ((lastKnownStatus == TorStatus.ON) && wasTorBootstrapped)
-
- val isDebugLoggingEnabled get() =
- context
- .getSharedPreferences("org.torproject.android_preferences", Context.MODE_PRIVATE)
- .getBoolean("pref_enable_logging", false)
-
- val isStarting get() = lastKnownStatus.isStarting()
- val isRestarting get() = isTorRestarting
- val isBootstrapped get() = isTorBootstrapped
- val isConnected get() = (lastKnownStatus.isStarted() && !isTorRestarting)
-
+interface TorController: TorEvents {
+ val logEntries: MutableList<Pair<String?, String?>>
+ val isStarting: Boolean
+ val isRestarting: Boolean
+ val isBootstrapped: Boolean
+ val isConnected: Boolean
var bridgesEnabled: Boolean
- get() = Prefs.bridgesEnabled()
- set(value) { Prefs.putBridgesEnabled(value) }
-
var bridgeTransport: TorBridgeTransportConfig
- get() {
- return TorBridgeTransportConfigUtil.getStringToBridgeTransport(
- Prefs.getBridgesList()
- )
- }
- set(value) {
- if (value == TorBridgeTransportConfig.USER_PROVIDED) {
- // Don't set the pref when the value is USER_PROVIDED because
- // "user_provided" is not a valid bridge or transport type.
- // This call should be followed by setting userProvidedBridges.
- return
- }
- Prefs.setBridgesList(value.transportName)
- }
-
var userProvidedBridges: String?
- get() {
- val bridges = Prefs.getBridgesList()
- val bridgeType =
- TorBridgeTransportConfigUtil.getStringToBridgeTransport(bridges)
- return when (bridgeType) {
- TorBridgeTransportConfig.USER_PROVIDED -> bridges
- else -> null
- }
- }
- set(value) {
- Prefs.setBridgesList(value)
- }
-
- fun start() {
- // Register receiver
- lbm.registerReceiver(
- persistentBroadcastReceiver,
- IntentFilter(TorServiceConstants.ACTION_STATUS)
- )
- lbm.registerReceiver(
- persistentBroadcastReceiver,
- IntentFilter(TorServiceConstants.LOCAL_ACTION_LOG)
- )
- }
- fun stop() {
- lbm.unregisterReceiver(persistentBroadcastReceiver)
- }
+ fun start()
+ fun stop()
- private val persistentBroadcastReceiver = object : BroadcastReceiver() {
- override fun onReceive(context: Context, intent: Intent) {
- if (intent.action == null ||
- (intent.action != TorServiceConstants.ACTION_STATUS &&
- intent.action != TorServiceConstants.LOCAL_ACTION_LOG)
- ) {
- return
- }
- val action = intent.action
+ override fun onTorConnecting()
+ override fun onTorConnected()
+ override fun onTorStatusUpdate(entry: String?, status: String?)
+ override fun onTorStopped()
- val logentry: String?
- val status: String?
- if (action == TorServiceConstants.LOCAL_ACTION_LOG) {
- logentry = intent.getExtras()
- ?.getCharSequence(TorServiceConstants.LOCAL_EXTRA_LOG) as? String?
- } else {
- logentry = null
- }
-
- status = intent.getExtras()
- ?.getCharSequence(TorServiceConstants.EXTRA_STATUS) as? String?
-
- if (logentry == null && status == null) {
- return
- }
-
- onTorStatusUpdate(logentry, status)
-
- if (status == null) {
- return
- }
-
- val newStatus = lastKnownStatus.getStateFromString(status)
-
- if (newStatus.isUnknown() && wasTorBootstrapped) {
- stopTor()
- }
-
- entries.add(Pair(logentry, status))
-
- if (logentry != null && logentry.contains(TorServiceConstants.TOR_CONTROL_PORT_MSG_BOOTSTRAP_DONE)) {
- wasTorBootstrapped = true
- onTorConnected()
- }
-
- if (lastKnownStatus.isStopping() && newStatus.isOff()) {
- if (isTorRestarting) {
- initiateTorBootstrap()
- } else {
- onTorStopped()
- }
- }
-
- if (lastKnownStatus.isOff() && newStatus.isStarting()) {
- isTorRestarting = false
- }
-
- lastKnownStatus = newStatus
- }
- }
-
- override fun onTorConnecting() {
- lockTorListenersMutation = true
- torListeners.forEach { it.onTorConnecting() }
- lockTorListenersMutation = false
-
- handlePendingRegistrationChanges()
- }
-
- override fun onTorConnected() {
- lockTorListenersMutation = true
- torListeners.forEach { it.onTorConnected() }
- lockTorListenersMutation = false
-
- handlePendingRegistrationChanges()
- }
+ fun registerTorListener(l: TorEvents)
+ fun unregisterTorListener(l: TorEvents)
- override fun onTorStatusUpdate(entry: String?, status: String?) {
- lockTorListenersMutation = true
- torListeners.forEach { it.onTorStatusUpdate(entry, status) }
- lockTorListenersMutation = false
-
- handlePendingRegistrationChanges()
- }
-
- override fun onTorStopped() {
- lockTorListenersMutation = true
- torListeners.forEach { it.onTorStopped() }
- lockTorListenersMutation = false
-
- handlePendingRegistrationChanges()
- }
-
- fun registerTorListener(l: TorEvents) {
- if (torListeners.contains(l)) {
- return
- }
-
- if (lockTorListenersMutation) {
- pendingRegisterChangeList.add(Pair(l, true))
- } else {
- torListeners.add(l)
- }
- }
-
- fun unregisterTorListener(l: TorEvents) {
- if (!torListeners.contains(l)) {
- return
- }
-
- if (lockTorListenersMutation) {
- pendingRegisterChangeList.add(Pair(l, false))
- } else {
- torListeners.remove(l)
- }
- }
-
- private fun handlePendingRegistrationChanges() {
- pendingRegisterChangeList.forEach {
- if (it.second) {
- registerTorListener(it.first)
- } else {
- unregisterTorListener(it.first)
- }
- }
-
- pendingRegisterChangeList.clear()
- }
-
- /**
- * Receive the current Tor status.
- *
- * Send a request for the current status and receive the response.
- * Returns true if Tor is running, false otherwise.
- *
- */
- private suspend fun checkTorIsStarted(): Boolean {
- val channel = Channel<Boolean>()
-
- // Register receiver
- val lbm: LocalBroadcastManager = LocalBroadcastManager.getInstance(context)
- val localBroadcastReceiver = object : BroadcastReceiver() {
- override fun onReceive(context: Context, intent: Intent) {
- val action = intent.action ?: return
- // We only want ACTION_STATUS messages
- if (action != TorServiceConstants.ACTION_STATUS) {
- return
- }
- // The current status has the EXTRA_STATUS key
- val currentStatus =
- intent.getStringExtra(TorServiceConstants.EXTRA_STATUS)
- channel.trySend(currentStatus === TorServiceConstants.STATUS_ON)
- }
- }
- lbm.registerReceiver(
- localBroadcastReceiver,
- IntentFilter(TorServiceConstants.ACTION_STATUS)
- )
-
- // Request service status
- sendServiceAction(TorServiceConstants.ACTION_STATUS)
-
- // Wait for response and unregister receiver
- var torIsStarted = false
- withTimeoutOrNull(torServiceResponseTimeout) {
- torIsStarted = channel.receive()
- }
- lbm.unregisterReceiver(localBroadcastReceiver)
- return torIsStarted
- }
-
- fun initiateTorBootstrap(lifecycleScope: LifecycleCoroutineScope? = null, withDebugLogging: Boolean = false) {
- if (BuildConfig.DISABLE_TOR) {
- return
- }
-
- context.getSharedPreferences("org.torproject.android_preferences", Context.MODE_PRIVATE)
- .edit().putBoolean("pref_enable_logging", withDebugLogging).apply()
-
- if (lifecycleScope == null) {
- sendServiceAction(TorServiceConstants.ACTION_START)
- } else {
- lifecycleScope.launch {
- val torNeedsStart = !checkTorIsStarted()
- if (torNeedsStart) {
- sendServiceAction(TorServiceConstants.ACTION_START)
- }
- }
- }
- }
-
- fun stopTor() {
- if (BuildConfig.DISABLE_TOR) {
- return
- }
-
- val torService = Intent(context, TorService::class.java)
- context.stopService(torService)
- }
-
- fun setTorStopped() {
- lastKnownStatus = TorStatus.OFF
- onTorStopped()
- }
-
- fun restartTor() {
- // tor-android-service doesn't dynamically update the torrc file,
- // and it doesn't use SETCONF, so we completely restart the service.
- // However, don't restart if we aren't started and we weren't
- // previously started.
- if (!lastKnownStatus.isStarted() && !wasTorBootstrapped) {
- return
- }
+ fun initiateTorBootstrap(lifecycleScope: LifecycleCoroutineScope? = null, withDebugLogging: Boolean = false)
+ fun stopTor()
+ fun setTorStopped()
+ fun restartTor()
+}
- if (!lastKnownStatus.isStarted() && wasTorBootstrapped) {
- // If we aren't started, but we were previously bootstrapped,
- // then we handle a "restart" request as a "start" restart
- initiateTorBootstrap()
- } else {
- // |isTorRestarting| tracks the state of restart. When we receive an |OFF| state
- // from TorService in persistentBroadcastReceiver::onReceive we restart the Tor
- // service.
- isTorRestarting = true
- stopTor()
- }
- }
- private fun sendServiceAction(action: String) {
- val torServiceStatus = Intent(context, TorService::class.java)
- torServiceStatus.action = action
- context.startService(torServiceStatus)
- }
- companion object {
- const val torServiceResponseTimeout = 5000L
- }
-}
=====================================
fenix/app/src/main/java/org/mozilla/fenix/tor/TorControllerGV.kt
=====================================
@@ -0,0 +1,289 @@
+package org.mozilla.fenix.tor
+
+
+import android.content.Context
+import android.util.Log
+import androidx.lifecycle.LifecycleCoroutineScope
+import mozilla.components.browser.engine.gecko.GeckoEngine
+import org.mozilla.fenix.ext.components
+import org.mozilla.geckoview.TorIntegrationAndroid
+import org.mozilla.geckoview.TorIntegrationAndroid.BootstrapStateChangeListener
+import org.mozilla.geckoview.TorSettings
+import org.mozilla.geckoview.TorSettings.BridgeBuiltinType
+import org.mozilla.geckoview.TorSettings.BridgeSource
+
+// Enum matching TorConnectState from TorConnect.sys.mjs that we get from onBootstrapStateChange
+internal enum class TorConnectState(val state: String) {
+ Initial("Initial"),
+ Configuring("Configuring"),
+ AutoBootstrapping("AutoBootstrapping"),
+ Bootstrapping("Bootstrapping"),
+ Error("Error"),
+ Bootstrapped("Bootstrapped"),
+ Disabled("Disabled");
+
+ fun isStarting() = this == Bootstrapping || this == AutoBootstrapping
+ fun isError() = this == Error
+
+ fun isStarted() = this == Bootstrapped
+
+ fun isOff() = this == Initial || this == Configuring || this == Disabled || this == Error
+
+
+ // Convert to TorStatus that firefox-android uses based on tor-android-service
+ fun toTorStatus(): TorStatus {
+ return when (this) {
+ Initial -> TorStatus.OFF
+ Configuring -> TorStatus.OFF
+ AutoBootstrapping -> TorStatus.STARTING
+ Bootstrapping -> TorStatus.STARTING
+ Error -> TorStatus.UNKNOWN
+ Bootstrapped -> TorStatus.ON
+ Disabled -> TorStatus.OFF
+ }
+ }
+}
+
+class TorControllerGV(
+ private val context: Context,
+) : TorController, TorEvents, BootstrapStateChangeListener {
+
+ private val TAG = "TorControllerGV"
+
+ private var torListeners = mutableListOf<TorEvents>()
+
+ private var lastKnownStatus = TorConnectState.Initial
+ private var wasTorBootstrapped = false
+ private var isTorRestarting = false
+
+ private var isTorBootstrapped = false
+ get() = ((lastKnownStatus.isStarted()) && wasTorBootstrapped)
+
+ private val entries = mutableListOf<Pair<String?, String?>>()
+ override val logEntries get() = entries
+ override val isStarting get() = lastKnownStatus.isStarting()
+ override val isRestarting get() = isTorRestarting
+ override val isBootstrapped get() = isTorBootstrapped
+ override val isConnected get() = (lastKnownStatus.isStarted() && !isTorRestarting)
+
+ private fun getTorIntegration(): TorIntegrationAndroid {
+ return (context.components.core.engine as GeckoEngine).getTorIntegrationController()
+ }
+
+ private fun getTorSettings(): TorSettings? {
+ return getTorIntegration().getSettings()
+ }
+
+ override var bridgesEnabled: Boolean
+ get() {
+ return getTorSettings()?.bridgesEnabled ?: false
+ }
+ set(value) {
+ getTorSettings()?.let {
+ it.bridgesEnabled = value
+ getTorIntegration().setSettings(it, true, true)
+ }
+ }
+
+
+ override var bridgeTransport: TorBridgeTransportConfig
+ get() {
+ return when (getTorSettings()?.bridgesSource) {
+ BridgeSource.BuiltIn -> {
+ when (getTorSettings()?.bridgesBuiltinType) {
+ BridgeBuiltinType.Obfs4 -> TorBridgeTransportConfig.BUILTIN_OBFS4
+ BridgeBuiltinType.MeekAzure -> TorBridgeTransportConfig.BUILTIN_MEEK_AZURE
+ BridgeBuiltinType.Snowflake -> TorBridgeTransportConfig.BUILTIN_SNOWFLAKE
+ else -> TorBridgeTransportConfig.USER_PROVIDED
+ }
+
+ }
+
+ BridgeSource.UserProvided -> TorBridgeTransportConfig.USER_PROVIDED
+ else -> TorBridgeTransportConfig.USER_PROVIDED
+ }
+ }
+ set(value) {
+ getTorSettings()?.let {
+ if (value == TorBridgeTransportConfig.USER_PROVIDED) {
+ it.bridgesSource = BridgeSource.BuiltIn
+ } else {
+ val bbt: BridgeBuiltinType = when (value) {
+ TorBridgeTransportConfig.BUILTIN_OBFS4 -> BridgeBuiltinType.Obfs4
+ TorBridgeTransportConfig.BUILTIN_MEEK_AZURE -> BridgeBuiltinType.MeekAzure
+ TorBridgeTransportConfig.BUILTIN_SNOWFLAKE -> BridgeBuiltinType.Snowflake
+ else -> BridgeBuiltinType.Invalid
+ }
+ it.bridgesBuiltinType = bbt
+ }
+ getTorIntegration().setSettings(it, true, true)
+ }
+ }
+
+
+ override var userProvidedBridges: String?
+ get() {
+ return getTorSettings()?.bridgeBridgeStrings?.joinToString("\r\n")
+ }
+ set(value) {
+ getTorSettings()?.let {
+ it.bridgeBridgeStrings = value?.split("\r\n")?.toTypedArray() ?: arrayOf<String>()
+ getTorIntegration().setSettings(it, true, true)
+ }
+ }
+
+ override fun start() {
+ getTorIntegration().registerBootstrapStateChangeListener(this)
+ }
+
+ override fun stop() {
+ getTorIntegration().unregisterBootstrapStateChangeListener(this)
+ }
+
+ // TorEvents
+ override fun onTorConnecting() {
+ synchronized(torListeners) {
+ torListeners.forEach { it.onTorConnecting() }
+ }
+ }
+
+ // TorEvents
+ override fun onTorConnected() {
+ synchronized(torListeners) {
+ torListeners.forEach { it.onTorConnected() }
+ }
+ }
+
+ // TorEvents
+ override fun onTorStatusUpdate(entry: String?, status: String?) {
+ synchronized(torListeners) {
+ torListeners.forEach { it.onTorStatusUpdate(entry, status) }
+ }
+ }
+
+ // TorEvents
+ override fun onTorStopped() {
+ synchronized(torListeners) {
+ torListeners.forEach { it.onTorStopped() }
+ }
+ }
+
+ override fun registerTorListener(l: TorEvents) {
+ synchronized(torListeners) {
+ if (torListeners.contains(l)) {
+ return
+ }
+ torListeners.add(l)
+ }
+ }
+
+ override fun unregisterTorListener(l: TorEvents) {
+ synchronized(torListeners) {
+ if (!torListeners.contains(l)) {
+ return
+ }
+ torListeners.remove(l)
+ }
+ }
+
+ override fun initiateTorBootstrap(
+ lifecycleScope: LifecycleCoroutineScope?,
+ withDebugLogging: Boolean,
+ ) {
+ getTorIntegration().beginBootstrap()
+ }
+
+ override fun stopTor() {
+ getTorIntegration().cancelBootstrap()
+ }
+
+ override fun setTorStopped() {
+ lastKnownStatus = TorConnectState.Disabled
+ onTorStopped()
+ }
+
+ override fun restartTor() {
+ if (!lastKnownStatus.isStarted() && wasTorBootstrapped) {
+ // If we aren't started, but we were previously bootstrapped,
+ // then we handle a "restart" request as a "start" restart
+ initiateTorBootstrap()
+ } else {
+ // |isTorRestarting| tracks the state of restart. When we receive an |OFF| state
+ // from TorService in persistentBroadcastReceiver::onReceive we restart the Tor
+ // service.
+ isTorRestarting = true
+ stopTor()
+ }
+ }
+
+ // TorEventsBootstrapStateChangeListener -> (lastKnowStatus, TorEvents)
+ // Handle events from GeckoView TorAndroidIntegration and map to TorEvents based events
+ // and state for firefox-android (designed for tor-android-service)
+ // fun onTorConnecting()
+ // fun onTorConnected()
+ // fun onTorStatusUpdate(entry: String?, status: String?)
+ // fun onTorStopped()
+
+ // TorEventsBootstrapStateChangeListener
+ override fun onBootstrapStateChange(newStateVal: String?) {
+ Log.d(TAG, "onBootstrapStateChange($newStateVal)")
+ val newState: TorConnectState = TorConnectState.valueOf(newStateVal ?: "Error")
+
+ if (newState.isError() && wasTorBootstrapped) {
+ stopTor()
+ }
+
+ if (newState.isStarted()) {
+ wasTorBootstrapped = true
+ onTorConnected()
+ }
+
+ if (wasTorBootstrapped && newState == TorConnectState.Configuring) {
+ wasTorBootstrapped = false
+ if (isTorRestarting) {
+ initiateTorBootstrap()
+ } else {
+ onTorStopped()
+ }
+ }
+
+ if (lastKnownStatus.isOff() && newState.isStarting()) {
+ isTorRestarting = false
+ }
+
+ lastKnownStatus = newState
+
+ }
+
+ // TorEventsBootstrapStateChangeListener
+ override fun onBootstrapProgress(progress: Double, status: String?, hasWarnings: Boolean) {
+ Log.d(TAG, "onBootstrapProgress($progress, $status, $hasWarnings)")
+ if (progress == 100.0) {
+ lastKnownStatus = TorConnectState.Bootstrapped
+ wasTorBootstrapped = true
+ onTorConnected()
+ } else {
+ lastKnownStatus = TorConnectState.Bootstrapping
+ onTorConnecting()
+
+ }
+ entries.add(Pair(status, lastKnownStatus.toTorStatus().status))
+ onTorStatusUpdate(status, lastKnownStatus.toTorStatus().status)
+ }
+
+ // TorEventsBootstrapStateChangeListener
+ override fun onBootstrapComplete() {
+ lastKnownStatus = TorConnectState.Bootstrapped
+ this.onTorConnected()
+ }
+
+ // TorEventsBootstrapStateChangeListener
+ override fun onBootstrapError(message: String?, details: String?) {
+ lastKnownStatus = TorConnectState.Error
+ }
+
+ // TorEventsBootstrapStateChangeListener
+ override fun onSettingsRequested() {
+ // noop
+ }
+}
=====================================
fenix/app/src/main/java/org/mozilla/fenix/tor/TorControllerTAS.kt
=====================================
@@ -0,0 +1,332 @@
+package org.mozilla.fenix.tor
+
+import android.content.BroadcastReceiver
+import android.content.Context
+import android.content.Intent
+import android.content.IntentFilter
+import androidx.lifecycle.LifecycleCoroutineScope
+import androidx.localbroadcastmanager.content.LocalBroadcastManager
+import kotlinx.coroutines.channels.Channel
+import kotlinx.coroutines.launch
+import kotlinx.coroutines.withTimeoutOrNull
+import org.mozilla.fenix.BuildConfig
+import org.torproject.android.service.TorService
+import org.torproject.android.service.TorServiceConstants
+import org.torproject.android.service.util.Prefs
+
+@SuppressWarnings("TooManyFunctions")
+class TorControllerTAS (private val context: Context): TorController {
+ private val lbm: LocalBroadcastManager = LocalBroadcastManager.getInstance(context)
+ private val entries = mutableListOf<Pair<String?, String?>>()
+ override val logEntries get() = entries
+
+ private var torListeners = mutableListOf<TorEvents>()
+
+ private var pendingRegisterChangeList = mutableListOf<Pair<TorEvents, Boolean>>()
+ private var lockTorListenersMutation = false
+
+ private var lastKnownStatus = TorStatus.OFF
+ private var wasTorBootstrapped = false
+ private var isTorRestarting = false
+
+ // This may be a lie
+ private var isTorBootstrapped = false
+ get() = ((lastKnownStatus == TorStatus.ON) && wasTorBootstrapped)
+
+ val isDebugLoggingEnabled get() =
+ context
+ .getSharedPreferences("org.torproject.android_preferences", Context.MODE_PRIVATE)
+ .getBoolean("pref_enable_logging", false)
+
+ override val isStarting get() = lastKnownStatus.isStarting()
+ override val isRestarting get() = isTorRestarting
+ override val isBootstrapped get() = isTorBootstrapped
+ override val isConnected get() = (lastKnownStatus.isStarted() && !isTorRestarting)
+
+ override var bridgesEnabled: Boolean
+ get() = Prefs.bridgesEnabled()
+ set(value) { Prefs.putBridgesEnabled(value) }
+
+ override var bridgeTransport: TorBridgeTransportConfig
+ get() {
+ return TorBridgeTransportConfigUtil.getStringToBridgeTransport(
+ Prefs.getBridgesList()
+ )
+ }
+ set(value) {
+ if (value == TorBridgeTransportConfig.USER_PROVIDED) {
+ // Don't set the pref when the value is USER_PROVIDED because
+ // "user_provided" is not a valid bridge or transport type.
+ // This call should be followed by setting userProvidedBridges.
+ return
+ }
+ Prefs.setBridgesList(value.transportName)
+ }
+
+ override var userProvidedBridges: String?
+ get() {
+ val bridges = Prefs.getBridgesList()
+ val bridgeType =
+ TorBridgeTransportConfigUtil.getStringToBridgeTransport(bridges)
+ return when (bridgeType) {
+ TorBridgeTransportConfig.USER_PROVIDED -> bridges
+ else -> null
+ }
+ }
+ set(value) {
+ Prefs.setBridgesList(value)
+ }
+
+ override fun start() {
+ // Register receiver
+ lbm.registerReceiver(
+ persistentBroadcastReceiver,
+ IntentFilter(TorServiceConstants.ACTION_STATUS)
+ )
+ lbm.registerReceiver(
+ persistentBroadcastReceiver,
+ IntentFilter(TorServiceConstants.LOCAL_ACTION_LOG)
+ )
+ }
+
+ override fun stop() {
+ lbm.unregisterReceiver(persistentBroadcastReceiver)
+ }
+
+ private val persistentBroadcastReceiver = object : BroadcastReceiver() {
+ override fun onReceive(context: Context, intent: Intent) {
+ if (intent.action == null ||
+ (intent.action != TorServiceConstants.ACTION_STATUS &&
+ intent.action != TorServiceConstants.LOCAL_ACTION_LOG)
+ ) {
+ return
+ }
+ val action = intent.action
+
+ val logentry: String?
+ val status: String?
+ if (action == TorServiceConstants.LOCAL_ACTION_LOG) {
+ logentry = intent.getExtras()
+ ?.getCharSequence(TorServiceConstants.LOCAL_EXTRA_LOG) as? String?
+ } else {
+ logentry = null
+ }
+
+ status = intent.getExtras()
+ ?.getCharSequence(TorServiceConstants.EXTRA_STATUS) as? String?
+
+ if (logentry == null && status == null) {
+ return
+ }
+
+ onTorStatusUpdate(logentry, status)
+
+ if (status == null) {
+ return
+ }
+
+ val newStatus = TorStatus.fromString(status)
+
+ if (newStatus.isUnknown() && wasTorBootstrapped) {
+ stopTor()
+ }
+
+ entries.add(Pair(logentry, status))
+
+ if (logentry != null && logentry.contains(TorServiceConstants.TOR_CONTROL_PORT_MSG_BOOTSTRAP_DONE)) {
+ wasTorBootstrapped = true
+ onTorConnected()
+ }
+
+ if (lastKnownStatus.isStopping() && newStatus.isOff()) {
+ if (isTorRestarting) {
+ initiateTorBootstrap()
+ } else {
+ onTorStopped()
+ }
+ }
+
+ if (lastKnownStatus.isOff() && newStatus.isStarting()) {
+ isTorRestarting = false
+ }
+
+ lastKnownStatus = newStatus
+ }
+ }
+
+ override fun onTorConnecting() {
+ lockTorListenersMutation = true
+ torListeners.forEach { it.onTorConnecting() }
+ lockTorListenersMutation = false
+
+ handlePendingRegistrationChanges()
+ }
+
+ override fun onTorConnected() {
+ lockTorListenersMutation = true
+ torListeners.forEach { it.onTorConnected() }
+ lockTorListenersMutation = false
+
+ handlePendingRegistrationChanges()
+ }
+
+ override fun onTorStatusUpdate(entry: String?, status: String?) {
+ lockTorListenersMutation = true
+ torListeners.forEach { it.onTorStatusUpdate(entry, status) }
+ lockTorListenersMutation = false
+
+ handlePendingRegistrationChanges()
+ }
+
+ override fun onTorStopped() {
+ lockTorListenersMutation = true
+ torListeners.forEach { it.onTorStopped() }
+ lockTorListenersMutation = false
+
+ handlePendingRegistrationChanges()
+ }
+
+ override fun registerTorListener(l: TorEvents) {
+ if (torListeners.contains(l)) {
+ return
+ }
+
+ if (lockTorListenersMutation) {
+ pendingRegisterChangeList.add(Pair(l, true))
+ } else {
+ torListeners.add(l)
+ }
+ }
+
+ override fun unregisterTorListener(l: TorEvents) {
+ if (!torListeners.contains(l)) {
+ return
+ }
+
+ if (lockTorListenersMutation) {
+ pendingRegisterChangeList.add(Pair(l, false))
+ } else {
+ torListeners.remove(l)
+ }
+ }
+
+ private fun handlePendingRegistrationChanges() {
+ pendingRegisterChangeList.forEach {
+ if (it.second) {
+ registerTorListener(it.first)
+ } else {
+ unregisterTorListener(it.first)
+ }
+ }
+
+ pendingRegisterChangeList.clear()
+ }
+
+ /**
+ * Receive the current Tor status.
+ *
+ * Send a request for the current status and receive the response.
+ * Returns true if Tor is running, false otherwise.
+ *
+ */
+ private suspend fun checkTorIsStarted(): Boolean {
+ val channel = Channel<Boolean>()
+
+ // Register receiver
+ val lbm: LocalBroadcastManager = LocalBroadcastManager.getInstance(context)
+ val localBroadcastReceiver = object : BroadcastReceiver() {
+ override fun onReceive(context: Context, intent: Intent) {
+ val action = intent.action ?: return
+ // We only want ACTION_STATUS messages
+ if (action != TorServiceConstants.ACTION_STATUS) {
+ return
+ }
+ // The current status has the EXTRA_STATUS key
+ val currentStatus =
+ intent.getStringExtra(TorServiceConstants.EXTRA_STATUS)
+ channel.trySend(currentStatus === TorServiceConstants.STATUS_ON)
+ }
+ }
+ lbm.registerReceiver(
+ localBroadcastReceiver,
+ IntentFilter(TorServiceConstants.ACTION_STATUS)
+ )
+
+ // Request service status
+ sendServiceAction(TorServiceConstants.ACTION_STATUS)
+
+ // Wait for response and unregister receiver
+ var torIsStarted = false
+ withTimeoutOrNull(torServiceResponseTimeout) {
+ torIsStarted = channel.receive()
+ }
+ lbm.unregisterReceiver(localBroadcastReceiver)
+ return torIsStarted
+ }
+
+ override fun initiateTorBootstrap(lifecycleScope: LifecycleCoroutineScope?, withDebugLogging: Boolean) {
+ if (BuildConfig.DISABLE_TOR) {
+ return
+ }
+
+ context.getSharedPreferences("org.torproject.android_preferences", Context.MODE_PRIVATE)
+ .edit().putBoolean("pref_enable_logging", withDebugLogging).apply()
+
+ if (lifecycleScope == null) {
+ sendServiceAction(TorServiceConstants.ACTION_START)
+ } else {
+ lifecycleScope.launch {
+ val torNeedsStart = !checkTorIsStarted()
+ if (torNeedsStart) {
+ sendServiceAction(TorServiceConstants.ACTION_START)
+ }
+ }
+ }
+ }
+
+ override fun stopTor() {
+ if (BuildConfig.DISABLE_TOR) {
+ return
+ }
+
+ val torService = Intent(context, TorService::class.java)
+ context.stopService(torService)
+ }
+
+ override fun setTorStopped() {
+ lastKnownStatus = TorStatus.OFF
+ onTorStopped()
+ }
+
+ override fun restartTor() {
+ // tor-android-service doesn't dynamically update the torrc file,
+ // and it doesn't use SETCONF, so we completely restart the service.
+ // However, don't restart if we aren't started and we weren't
+ // previously started.
+ if (!lastKnownStatus.isStarted() && !wasTorBootstrapped) {
+ return
+ }
+
+ if (!lastKnownStatus.isStarted() && wasTorBootstrapped) {
+ // If we aren't started, but we were previously bootstrapped,
+ // then we handle a "restart" request as a "start" restart
+ initiateTorBootstrap()
+ } else {
+ // |isTorRestarting| tracks the state of restart. When we receive an |OFF| state
+ // from TorService in persistentBroadcastReceiver::onReceive we restart the Tor
+ // service.
+ isTorRestarting = true
+ stopTor()
+ }
+ }
+
+ private fun sendServiceAction(action: String) {
+ val torServiceStatus = Intent(context, TorService::class.java)
+ torServiceStatus.action = action
+ context.startService(torServiceStatus)
+ }
+
+ companion object {
+ const val torServiceResponseTimeout = 5000L
+ }
+}
View it on GitLab: https://gitlab.torproject.org/tpo/applications/firefox-android/-/commit/6d0…
--
View it on GitLab: https://gitlab.torproject.org/tpo/applications/firefox-android/-/commit/6d0…
You're receiving this email because of your account on gitlab.torproject.org.
[View Less]
1
0