Skip to content

Commit

Permalink
Use cached file from config app in fetching content filtering file
Browse files Browse the repository at this point in the history
  • Loading branch information
quh4gko8 authored and thestinger committed Jul 16, 2024
1 parent cc0e78d commit 813f476
Show file tree
Hide file tree
Showing 6 changed files with 659 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,191 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: fgei <[email protected]>
Date: Mon, 15 Jul 2024 15:29:50 +0000
Subject: [PATCH] Include a java port of atomic file and scoped file descriptor
utility classes from Apps app

---
vanadium/ext/utils/BUILD.gn | 14 +++
.../app/vanadium/ext/utils/AtomicFile2.java | 101 ++++++++++++++++++
.../ext/utils/ScopedFileDescriptor.java | 42 ++++++++
3 files changed, 157 insertions(+)
create mode 100644 vanadium/ext/utils/BUILD.gn
create mode 100644 vanadium/ext/utils/java/src/app/vanadium/ext/utils/AtomicFile2.java
create mode 100644 vanadium/ext/utils/java/src/app/vanadium/ext/utils/ScopedFileDescriptor.java

diff --git a/vanadium/ext/utils/BUILD.gn b/vanadium/ext/utils/BUILD.gn
new file mode 100644
index 0000000000000..bc05f3660d5b3
--- /dev/null
+++ b/vanadium/ext/utils/BUILD.gn
@@ -0,0 +1,14 @@
+# Copyright 2023 GrapheneOS
+# Use of this source code is governed by a GPL-2.0 style license that can be
+# found in the LICENSE file.
+
+import("//build/config/android/rules.gni")
+
+android_library("file_utils_java") {
+ sources = [
+ "java/src/app/vanadium/ext/utils/AtomicFile2.java",
+ "java/src/app/vanadium/ext/utils/ScopedFileDescriptor.java",
+ ]
+ deps = [
+ ]
+}
\ No newline at end of file
diff --git a/vanadium/ext/utils/java/src/app/vanadium/ext/utils/AtomicFile2.java b/vanadium/ext/utils/java/src/app/vanadium/ext/utils/AtomicFile2.java
new file mode 100644
index 0000000000000..e684ba75ee4db
--- /dev/null
+++ b/vanadium/ext/utils/java/src/app/vanadium/ext/utils/AtomicFile2.java
@@ -0,0 +1,101 @@
+package app.vanadium.ext.utils;
+
+import android.content.Context;
+import android.os.Build;
+import android.system.ErrnoException;
+import android.system.Os;
+import android.system.OsConstants;
+import android.util.Log;
+
+
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InterruptedIOException;
+import java.nio.file.Files;
+
+// Class authored by muhomorr in Apps app repository, see
+// https://github.com/GrapheneOS/Apps/commit/43e9d5218374e712f96154b269e554b2debd652d#diff-d95bcaf27889d24a999547d34ab4a980c248cd9f048aebf27524cdc103e58b47
+// and the copied documentation below:
+// android.util.AtomicFile has several issues:
+// - ignores errors from fsync(), rename(), close()
+// - doesn't do fsync of the containing directory
+// - doesn't enforce having at most one writer at a time
+// - checks for a legacy file name that was used by its older implementation
+public final class AtomicFile2 {
+
+ public static final String TAG = "cr_AtomicFile2";
+
+ public final String name;
+ public final String dirPath;
+ private final File file;
+ public final String filePath;
+ private final String tmpFilePath;
+
+ // Context.getFilesDir() is the only reliable place to write files: files from cache dir may
+ // disappear mid-write, before rename of tmpPath. Writes to files on shared storage go through
+ // the FUSE daemon, which lowers reliability and performance
+ public AtomicFile2(Context ctx, String name) {
+ File filesDir = ctx.getFilesDir();
+ this.name = name;
+ this.dirPath = filesDir.getPath();
+ this.file = new File(filesDir, name);
+ this.filePath = this.file.getPath();
+ this.tmpFilePath = this.filePath + ".tmp";
+ }
+
+ public byte[] read() throws IOException {
+ if (!file.exists()) {
+ return null;
+ }
+
+ try {
+ return Files.readAllBytes(file.toPath());
+ } catch (IOException e) {
+ Log.e(TAG, "", e);
+ return null;
+ }
+ }
+
+ public boolean delete() {
+ synchronized (file) {
+ return file.delete();
+ }
+ }
+
+ public void write(byte[] bytes) throws ErrnoException, InterruptedIOException {
+ synchronized (file) {
+ writeInner(bytes);
+ }
+ }
+
+ private void writeInner(byte[] bytes) throws ErrnoException, InterruptedIOException {
+ int flags = OsConstants.O_RDWR | OsConstants.O_CREAT |
+ // in case there's a leftover file from previous failed write
+ OsConstants.O_TRUNC;
+ int mode = OsConstants.S_IRUSR | OsConstants.S_IWUSR; // 0600
+
+ try (ScopedFileDescriptor sfd =
+ new ScopedFileDescriptor(Os.open(tmpFilePath, flags, mode))) {
+ int written = 0;
+ int len = bytes.length;
+ while (written != len) {
+ int chunkLen = len - written;
+ int writeRes = Os.write(sfd.v, bytes, written, chunkLen);
+ if (writeRes < 0 || writeRes > chunkLen) {
+ throw new IllegalStateException("unexpected write result and chunk to write");
+ }
+ written += writeRes;
+ }
+
+ Os.fsync(sfd.v);
+ }
+
+ Os.rename(tmpFilePath, filePath);
+
+ try (var fd = new ScopedFileDescriptor(Os.open(dirPath, OsConstants.O_RDONLY, 0))) {
+ Os.fsync(fd.v);
+ }
+ }
+}
diff --git a/vanadium/ext/utils/java/src/app/vanadium/ext/utils/ScopedFileDescriptor.java b/vanadium/ext/utils/java/src/app/vanadium/ext/utils/ScopedFileDescriptor.java
new file mode 100644
index 0000000000000..7934567ff189e
--- /dev/null
+++ b/vanadium/ext/utils/java/src/app/vanadium/ext/utils/ScopedFileDescriptor.java
@@ -0,0 +1,42 @@
+package app.vanadium.ext.utils;
+
+import android.content.Context;
+import android.os.ParcelFileDescriptor;
+import android.system.ErrnoException;
+import android.system.Os;
+import android.system.OsConstants;
+import android.util.Log;
+
+import java.io.File;
+import java.io.FileDescriptor;
+import java.io.IOException;
+
+// Class authored by muhomorr in Apps app repository, see
+// https://github.com/GrapheneOS/Apps/commit/43e9d5218374e712f96154b269e554b2debd652d#diff-d95bcaf27889d24a999547d34ab4a980c248cd9f048aebf27524cdc103e58b47
+// and the copied documentation below:
+public final class ScopedFileDescriptor implements AutoCloseable {
+
+ public static final String TAG = "cr_ScopedFileDescriptor";
+
+ public final FileDescriptor v;
+
+ public ScopedFileDescriptor(FileDescriptor v) {
+ this.v = v;
+ }
+
+ // Needed for accessing the int value of fd.
+ // Strangely, access to int value of FileDescriptor is restricted behind hidden and discouraged
+ // FileDescriptor.getInt$(), but is part of public API of ParcelFileDescriptor
+ public ParcelFileDescriptor dupToFd() throws IOException {
+ return ParcelFileDescriptor.dup(v);
+ }
+
+ @Override
+ public void close() {
+ try {
+ Os.close(v);
+ } catch (ErrnoException e) {
+ Log.d(TAG, "", e);
+ }
+ }
+}
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: fgei <[email protected]>
Date: Mon, 15 Jul 2024 15:40:55 +0000
Subject: [PATCH] Add support for upstream file-based parsing of unindexed
content filtering component

---
vanadium/android_config/proto/BUILD.gn | 2 +
.../SubresourceFilterComponentUtils.java | 78 +++++++++++++++++++
.../vanadium/config/VanadiumConfParser.java | 3 +
3 files changed, 83 insertions(+)
create mode 100644 vanadium/android_config/proto/java/src/app/vanadium/config/SubresourceFilterComponentUtils.java

diff --git a/vanadium/android_config/proto/BUILD.gn b/vanadium/android_config/proto/BUILD.gn
index 5f04b2dca6267..497fd12a4671c 100644
--- a/vanadium/android_config/proto/BUILD.gn
+++ b/vanadium/android_config/proto/BUILD.gn
@@ -54,12 +54,14 @@ action("config_generation") {

android_library("browser_config_parser_java") {
sources = [
+ "java/src/app/vanadium/config/SubresourceFilterComponentUtils.java",
"java/src/app/vanadium/config/VanadiumConfConditionals.java",
"java/src/app/vanadium/config/VanadiumConfParser.java",
]
deps = [
":config_proto_java",
"//vanadium/android_config:configinfo_java",
+ "//vanadium/ext/utils:file_utils_java",
]
}

diff --git a/vanadium/android_config/proto/java/src/app/vanadium/config/SubresourceFilterComponentUtils.java b/vanadium/android_config/proto/java/src/app/vanadium/config/SubresourceFilterComponentUtils.java
new file mode 100644
index 0000000000000..a42d38734d266
--- /dev/null
+++ b/vanadium/android_config/proto/java/src/app/vanadium/config/SubresourceFilterComponentUtils.java
@@ -0,0 +1,78 @@
+package app.vanadium.config;
+
+import android.content.Context;
+import android.system.ErrnoException;
+import android.util.Log;
+
+import java.io.InterruptedIOException;
+import java.util.Objects;
+
+import app.vanadium.config.proto.VanadiumConfigProto;
+import app.vanadium.ext.utils.AtomicFile2;
+
+public final class SubresourceFilterComponentUtils {
+
+ private static final String UNINDEXED_RULESET_FILE_NAME = "unindexed_subresource_filter";
+ private static final String TAG = "cr_SubresourceFilterComponentUtils";
+
+ private static SubresourceFilterComponentUtils instance;
+ private static volatile boolean initialized = false;
+
+ private final AtomicFile2 atomicFileForParsing;
+
+ SubresourceFilterComponentUtils(Context appCtx) {
+ this.atomicFileForParsing = new AtomicFile2(appCtx, UNINDEXED_RULESET_FILE_NAME);
+ }
+
+ static SubresourceFilterComponentUtils initialize(Context appCtx) {
+ if (initialized) {
+ return instance;
+ }
+
+ instance = new SubresourceFilterComponentUtils(appCtx);
+ initialized = true;
+ return instance;
+ }
+
+ private static SubresourceFilterComponentUtils getInstance() {
+ if (!initialized || instance == null) {
+ Log.w(TAG, "not yet initialized", new Throwable());
+ return null;
+ }
+
+ return instance;
+ }
+
+ public static void writeCurrentContents() {
+ SubresourceFilterComponentUtils instance = getInstance();
+ if (instance == null) {
+ return;
+ }
+
+ try {
+ instance.atomicFileForParsing.write(
+ VanadiumConfParser.getByteArrayForComponent(
+ VanadiumConfigProto.Component.ComponentType.SUBRESOURCE_FILTER_TOOLS));
+ } catch (ErrnoException | InterruptedIOException e) {
+ Log.e(TAG, "", e);
+ }
+ }
+
+ public static boolean deleteComponentFileForParsing() {
+ SubresourceFilterComponentUtils instance = getInstance();
+ if (instance == null) {
+ return false;
+ }
+
+ return instance.atomicFileForParsing.delete();
+ }
+
+ public static String getFilePathForParsing() {
+ SubresourceFilterComponentUtils instance = getInstance();
+ if (instance == null) {
+ return null;
+ }
+
+ return instance.atomicFileForParsing.filePath;
+ }
+}
diff --git a/vanadium/android_config/proto/java/src/app/vanadium/config/VanadiumConfParser.java b/vanadium/android_config/proto/java/src/app/vanadium/config/VanadiumConfParser.java
index bdb3bf71cebcc..76fcd33f74909 100644
--- a/vanadium/android_config/proto/java/src/app/vanadium/config/VanadiumConfParser.java
+++ b/vanadium/android_config/proto/java/src/app/vanadium/config/VanadiumConfParser.java
@@ -329,6 +329,9 @@ public final class VanadiumConfParser {
private static void parseInBackground(Context ctx, SpecType specType) {
futureParsedConfigs = executor.submit(() -> {
parsedConfigs = parse(ctx, specType);
+ if (parsedConfigs != null) {
+ SubresourceFilterComponentUtils.initialize(ctx);
+ }
return parsedConfigs;
});
}
Loading

0 comments on commit 813f476

Please sign in to comment.