From 77eda90923dc5f968a4054e27e9ddeed6344df09 Mon Sep 17 00:00:00 2001 From: link2xt Date: Sat, 22 Nov 2025 16:40:58 +0000 Subject: [PATCH] Add WebxdcGarbageCollectionWorker --- build.gradle | 1 + .../securesms/ApplicationContext.java | 50 ++++--------- .../WebxdcGarbageCollectionWorker.java | 71 +++++++++++++++++++ 3 files changed, 84 insertions(+), 38 deletions(-) create mode 100644 src/main/java/org/thoughtcrime/securesms/connect/WebxdcGarbageCollectionWorker.java diff --git a/build.gradle b/build.gradle index 22185c889..6eb9cf0d0 100644 --- a/build.gradle +++ b/build.gradle @@ -152,6 +152,7 @@ android { } dependencies { + implementation 'androidx.concurrent:concurrent-futures:1.3.0' implementation 'androidx.sharetarget:sharetarget:1.2.0' implementation 'androidx.webkit:webkit:1.14.0' implementation 'androidx.multidex:multidex:2.0.1' diff --git a/src/main/java/org/thoughtcrime/securesms/ApplicationContext.java b/src/main/java/org/thoughtcrime/securesms/ApplicationContext.java index 36805ae09..f6feb7a74 100644 --- a/src/main/java/org/thoughtcrime/securesms/ApplicationContext.java +++ b/src/main/java/org/thoughtcrime/securesms/ApplicationContext.java @@ -31,6 +31,7 @@ import org.thoughtcrime.securesms.connect.AccountManager; import org.thoughtcrime.securesms.connect.DcEventCenter; import org.thoughtcrime.securesms.connect.DcHelper; import org.thoughtcrime.securesms.connect.FetchWorker; +import org.thoughtcrime.securesms.connect.WebxdcGarbageCollectionWorker; import org.thoughtcrime.securesms.connect.ForegroundDetector; import org.thoughtcrime.securesms.connect.KeepAliveService; import org.thoughtcrime.securesms.connect.NetworkStateReceiver; @@ -222,44 +223,17 @@ public class ApplicationContext extends MultiDexApplication { fetchWorkRequest); } - Util.runOnBackground(() -> { - Util.sleep(10*1000); // 10s delay to avoid startup bottleneck - final Pattern WEBXDC_URL_PATTERN = - Pattern.compile("^https?://acc(\\d+)-msg(\\d+)\\.localhost/?"); - while (true) { - Log.i(TAG, "Running Webxdc storage garbage collection..."); - WebStorage webStorage = WebStorage.getInstance(); - webStorage.getOrigins((origins) -> { - if (origins == null || origins.isEmpty()) { - Log.i(TAG, "Done, no WebView origins found."); - return; - } - - for (Object key : origins.keySet()) { - String url = (String)key; - Matcher m = WEBXDC_URL_PATTERN.matcher(url); - if (m.matches()) { - int accId = Integer.parseInt(m.group(1)); - int msgId = Integer.parseInt(m.group(2)); - try { - rpc.getMessage(accId, msgId); - Log.i(TAG, String.format("Existing webxdc origin: %s", url)); - } catch (RpcException ignore) { - // msg doesn't exist anymore, clean storage - webStorage.deleteOrigin(url); - Log.i(TAG, String.format("Deleted webxdc origin: %s", url)); - } - } else { // old webxdc URL schemes, etc - webStorage.deleteOrigin(url); - Log.i(TAG, String.format("Deleted unknown origin: %s", url)); - } - } - - Log.i(TAG, "Done running Webxdc storage garbage collection."); - }); - Util.sleep(60*60*1000); // 1h - } - }); + PeriodicWorkRequest webxdcGarbageCollectionRequest = new PeriodicWorkRequest.Builder( + WebxdcGarbageCollectionWorker.class, + PeriodicWorkRequest.MIN_PERIODIC_INTERVAL_MILLIS, + TimeUnit.MILLISECONDS, + PeriodicWorkRequest.MIN_PERIODIC_FLEX_MILLIS, + TimeUnit.MILLISECONDS) + .build(); + WorkManager.getInstance(this).enqueueUniquePeriodicWork( + "WebxdcGarbageCollectionWorker", + ExistingPeriodicWorkPolicy.KEEP, + webxdcGarbageCollectionRequest); } public JobManager getJobManager() { diff --git a/src/main/java/org/thoughtcrime/securesms/connect/WebxdcGarbageCollectionWorker.java b/src/main/java/org/thoughtcrime/securesms/connect/WebxdcGarbageCollectionWorker.java new file mode 100644 index 000000000..0212b0f77 --- /dev/null +++ b/src/main/java/org/thoughtcrime/securesms/connect/WebxdcGarbageCollectionWorker.java @@ -0,0 +1,71 @@ +package org.thoughtcrime.securesms.connect; + +import android.content.Context; +import android.util.Log; +import android.webkit.WebStorage; +import androidx.annotation.NonNull; +import androidx.concurrent.futures.CallbackToFutureAdapter; +import androidx.work.ListenableWorker; +import androidx.work.WorkerParameters; +import chat.delta.rpc.Rpc; +import chat.delta.rpc.RpcException; +import com.google.common.util.concurrent.ListenableFuture; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import org.thoughtcrime.securesms.connect.DcHelper; +import org.thoughtcrime.securesms.util.Util; + +public class WebxdcGarbageCollectionWorker extends ListenableWorker { + private static final String TAG = WebxdcGarbageCollectionWorker.class.getSimpleName(); + private Rpc rpc; + + public WebxdcGarbageCollectionWorker(Context context, WorkerParameters params) { + super(context, params); + rpc = DcHelper.getRpc(context); + } + + @Override + public @NonNull ListenableFuture startWork() { + Log.i(TAG, "Running Webxdc storage garbage collection..."); + + final Pattern WEBXDC_URL_PATTERN = + Pattern.compile("^https?://acc(\\d+)-msg(\\d+)\\.localhost/?"); + + return CallbackToFutureAdapter.getFuture(completer -> { + WebStorage webStorage = WebStorage.getInstance(); + + webStorage.getOrigins((origins) -> { + if (origins == null || origins.isEmpty()) { + Log.i(TAG, "Done, no WebView origins found."); + completer.set(Result.success()); + return; + } + + for (Object key : origins.keySet()) { + String url = (String)key; + Matcher m = WEBXDC_URL_PATTERN.matcher(url); + if (m.matches()) { + int accId = Integer.parseInt(m.group(1)); + int msgId = Integer.parseInt(m.group(2)); + try { + rpc.getMessage(accId, msgId); + Log.i(TAG, String.format("Existing webxdc origin: %s", url)); + } catch (RpcException ignore) { + // msg doesn't exist anymore, clean storage + webStorage.deleteOrigin(url); + Log.i(TAG, String.format("Deleted webxdc origin: %s", url)); + } + } else { // old webxdc URL schemes, etc + webStorage.deleteOrigin(url); + Log.i(TAG, String.format("Deleted unknown origin: %s", url)); + } + } + + Log.i(TAG, "Done running Webxdc storage garbage collection."); + completer.set(Result.success()); + }); + + return "Webxdc Garbage Collector"; + }); + } +}