diff --git a/data/dev.geopjr.Tuba.gschema.xml b/data/dev.geopjr.Tuba.gschema.xml
index e0d6d0a88..88b49f13d 100644
--- a/data/dev.geopjr.Tuba.gschema.xml
+++ b/data/dev.geopjr.Tuba.gschema.xml
@@ -48,6 +48,9 @@
false
+
+ true
+
-1
diff --git a/data/ui/dialogs/preferences.ui b/data/ui/dialogs/preferences.ui
index 215b6d095..334fdec30 100644
--- a/data/ui/dialogs/preferences.ui
+++ b/data/ui/dialogs/preferences.ui
@@ -111,6 +111,18 @@
+
+
+
diff --git a/src/Dialogs/Preferences.vala b/src/Dialogs/Preferences.vala
index bf7fcde76..625ace645 100644
--- a/src/Dialogs/Preferences.vala
+++ b/src/Dialogs/Preferences.vala
@@ -15,6 +15,7 @@ public class Tuba.Dialogs.Preferences : Adw.PreferencesWindow {
[GtkChild] unowned Switch hide_preview_cards;
[GtkChild] unowned Switch larger_font_size;
[GtkChild] unowned Switch larger_line_height;
+ [GtkChild] unowned Switch strip_tracking;
private bool lang_changed { get; set; default=false; }
@@ -59,6 +60,7 @@ public class Tuba.Dialogs.Preferences : Adw.PreferencesWindow {
settings.bind ("hide-preview-cards", hide_preview_cards, "active", SettingsBindFlags.DEFAULT);
settings.bind ("larger-font-size", larger_font_size, "active", SettingsBindFlags.DEFAULT);
settings.bind ("larger-line-height", larger_line_height, "active", SettingsBindFlags.DEFAULT);
+ settings.bind ("strip-tracking", strip_tracking, "active", SettingsBindFlags.DEFAULT);
post_visibility_combo_row.notify["selected-item"].connect(on_post_visibility_changed);
diff --git a/src/Services/Settings.vala b/src/Services/Settings.vala
index d608134af..8dfe518ac 100644
--- a/src/Services/Settings.vala
+++ b/src/Services/Settings.vala
@@ -16,6 +16,7 @@ public class Tuba.Settings : GLib.Settings {
public bool larger_font_size { get; set; }
public bool larger_line_height { get; set; }
public bool aggressive_resolving { get; set; }
+ public bool strip_tracking { get; set; }
public Settings () {
Object (schema_id: Build.DOMAIN);
@@ -32,6 +33,7 @@ public class Tuba.Settings : GLib.Settings {
init ("larger-font-size");
init ("larger-line-height");
init ("aggressive-resolving");
+ init ("strip-tracking");
}
void init (string key) {
diff --git a/src/Utils/Host.vala b/src/Utils/Host.vala
index b48339450..deacf6328 100644
--- a/src/Utils/Host.vala
+++ b/src/Utils/Host.vala
@@ -9,6 +9,8 @@ public class Tuba.Host {
if (!(":" in uri))
uri = "file://" + _uri;
+ if (settings.strip_tracking)
+ uri = Tracking.strip_utm (uri);
message (@"Opening URI: $uri");
try {
var success = AppInfo.launch_default_for_uri (uri, null);
diff --git a/src/Utils/Tracking.vala b/src/Utils/Tracking.vala
new file mode 100644
index 000000000..9c6a54a74
--- /dev/null
+++ b/src/Utils/Tracking.vala
@@ -0,0 +1,114 @@
+// Ported from Chatty
+// https://source.puri.sm/Librem5/chatty/-/merge_requests/1229
+
+public class Tuba.Tracking {
+ /* https://github.com/brave/brave-core/blob/5fcad3e35bac6fea795941fd8189a59d79d488bc/browser/net/brave_site_hacks_network_delegate_helper.cc#L29-L67 */
+ public const string[] tracking_ids = {
+ // Strip any utm_ based ones
+ "utm_",
+ // https://github.com/brave/brave-browser/issues/4239
+ "fbclid", "gclid", "msclkid", "mc_eid",
+ // https://github.com/brave/brave-browser/issues/9879
+ "dclid",
+ // https://github.com/brave/brave-browser/issues/13644
+ "oly_anon_id", "oly_enc_id",
+ // https://github.com/brave/brave-browser/issues/11579
+ "_openstat",
+ // https://github.com/brave/brave-browser/issues/11817
+ "vero_conv", "vero_id",
+ // https://github.com/brave/brave-browser/issues/13647
+ "wickedid",
+ // https://github.com/brave/brave-browser/issues/11578
+ "yclid",
+ // https://github.com/brave/brave-browser/issues/8975
+ "__s",
+ // https://github.com/brave/brave-browser/issues/17451
+ "rb_clickid",
+ // https://github.com/brave/brave-browser/issues/17452
+ "s_cid",
+ // https://github.com/brave/brave-browser/issues/17507
+ "ml_subscriber", "ml_subscriber_hash",
+ // https://github.com/brave/brave-browser/issues/18020
+ "twclid",
+ // https://github.com/brave/brave-browser/issues/18758
+ "gbraid", "wbraid",
+ // https://github.com/brave/brave-browser/issues/9019
+ "_hsenc", "__hssc", "__hstc", "__hsfp", "hsCtaTracking",
+ // https://github.com/brave/brave-browser/issues/22082
+ "oft_id", "oft_k", "oft_lk", "oft_d", "oft_c", "oft_ck", "oft_ids", "oft_sk",
+ // https://github.com/brave/brave-browser/issues/11580
+ "igshid",
+ };
+
+ public static string strip_utm (string url) {
+ if (!("?" in url)) return url;
+
+ try {
+ var uri = Uri.parse (url, UriFlags.NONE);
+ return strip_utm_from_uri (uri).to_string ();
+ } catch (GLib.UriError e) {
+ warning (e.message);
+ return strip_utm_fallback (url);
+ }
+ }
+
+ public static Uri strip_utm_from_uri (Uri uri) throws UriError {
+ var uri_params = Uri.parse_params (uri.get_query ());
+ string[] res_params = {};
+
+ uri_params.foreach_remove ((key, val) => {
+ var not_tracking_id = true;
+ foreach (var id in tracking_ids) {
+ if (id in key.down ()) {
+ not_tracking_id = false;
+ break;
+ }
+ }
+
+ if (not_tracking_id) res_params += @"$key=$val";
+
+ return !not_tracking_id;
+ });
+
+ string? res_query = res_params.length > 0 ? string.joinv("&", res_params) : null;
+ return Uri.build (
+ uri.get_flags (),
+ uri.get_scheme(),
+ uri.get_userinfo (),
+ uri.get_host (),
+ uri.get_port (),
+ uri.get_path (),
+ res_query,
+ uri.get_fragment ()
+ );
+ }
+
+ public static string strip_utm_fallback (string url) {
+ var split_url = url.split_set ("?", 2);
+ if (split_url[1].index_of_char ('=') == -1) return url;
+
+ var query_params = split_url[1].split_set ("&");
+ var str = @"$(split_url[0])?";
+
+ var fragment_offset = split_url[1].last_index_of_char ('#');
+ var fragment = fragment_offset > -1 ? split_url[1].substring(fragment_offset) : "";
+
+ foreach (var param in query_params) {
+ var not_tracking_id = true;
+
+ foreach (var id in tracking_ids) {
+ var index_of_eq = param.index_of_char ('=');
+ if (index_of_eq > -1 && id in param.slice (0, index_of_eq).down ()) {
+ not_tracking_id = false;
+ break;
+ }
+ }
+
+ if (not_tracking_id) {
+ str += @"$(param)&";
+ }
+ }
+
+ return @"$(str.slice(0, -1))$fragment";
+ }
+}
diff --git a/src/Utils/meson.build b/src/Utils/meson.build
index 240751856..186b6cd90 100644
--- a/src/Utils/meson.build
+++ b/src/Utils/meson.build
@@ -3,4 +3,5 @@ sources += files(
'Host.vala',
'Html.vala',
'Locale.vala',
+ 'Tracking.vala',
)