Repository: sissbruecker/linkding
Pull request #866 (2024-09-29 10:05:43)

Replace uBlock Origin with uBlock Origin Lite
uBlock Origin does not work anymore in latest Chrome / Chromium versions due to the removal of the Manifest V2 extension API. The linkding `latest-plus-alpine` image is already affected by this in that the extension doesn't load anymore, causing HTML snapshots to fail. The Debian image will also be affected once they upgrade to a more recent Chrome version.

This replaces uBlock Origin with uBlock Origin Lite which does work with newer Chromium versions.

Fixes https://github.com/sissbruecker/linkding/issues/864


Patch:
diff --git a/.gitignore b/.gitignore
index 5850eb5..68fad2d 100644
--- a/.gitignore
+++ b/.gitignore
@@ -192,7 +192,7 @@ typings/
 # Database file
 /data
 # ublock + chromium
-/uBlock0.chromium
+/uBOLite.chromium.mv3
 /chromium-profile
 # direnv
 /.direnv
diff --git a/docker/alpine.Dockerfile b/docker/alpine.Dockerfile
index e8c2210..74e2aa8 100644
--- a/docker/alpine.Dockerfile
+++ b/docker/alpine.Dockerfile
@@ -88,18 +88,20 @@ CMD ["./bootstrap.sh"]
 FROM node:18-alpine AS ublock-build
 WORKDIR /etc/linkding
 # Install necessary tools
-RUN apk add --no-cache curl jq unzip
-# Fetch the latest release tag
-# Download the library
-# Unzip the library
-RUN TAG=$(curl -sL https://api.github.com/repos/gorhill/uBlock/releases/latest | jq -r '.tag_name') && \
-    DOWNLOAD_URL=https://github.com/gorhill/uBlock/releases/download/$TAG/uBlock0_$TAG.chromium.zip && \
-    curl -L -o uBlock0.zip $DOWNLOAD_URL && \
-    unzip uBlock0.zip
-# Patch assets.json to enable easylist-cookies by default
-RUN curl -L -o ./uBlock0.chromium/assets/thirdparties/easylist/easylist-cookies.txt https://ublockorigin.github.io/uAssets/thirdparties/easylist-cookies.txt
-RUN jq '."assets.json" |= del(.cdnURLs) | ."assets.json".contentURL = ["assets/assets.json"] | ."fanboy-cookiemonster" |= del(.off) | ."fanboy-cookiemonster".contentURL += ["assets/thirdparties/easylist/easylist-cookies.txt"]' ./uBlock0.chromium/assets/assets.json > temp.json && \
-    mv temp.json ./uBlock0.chromium/assets/assets.json
+# Download and unzip the latest uBlock Origin Lite release
+# Patch manifest to enable annoyances by default
+# Patch ruleset-manager.js to use rulesets enabled in manifest by default
+RUN apk add --no-cache curl jq unzip && \
+    TAG=$(curl -sL https://api.github.com/repos/uBlockOrigin/uBOL-home/releases/latest | jq -r '.tag_name') && \
+    DOWNLOAD_URL=https://github.com/uBlockOrigin/uBOL-home/releases/download/$TAG/$TAG.chromium.mv3.zip && \
+    echo "Downloading $DOWNLOAD_URL" && \
+    curl -L -o uBOLite.zip $DOWNLOAD_URL && \
+    unzip uBOLite.zip -d uBOLite.chromium.mv3 && \
+    rm uBOLite.zip && \
+    jq '.declarative_net_request.rule_resources |= map(if .id == "annoyances-overlays" or .id == "annoyances-cookies" or .id == "annoyances-social" or .id == "annoyances-widgets" or .id == "annoyances-others" then .enabled = true else . end)' \
+        uBOLite.chromium.mv3/manifest.json > temp.json && \
+    mv temp.json uBOLite.chromium.mv3/manifest.json && \
+    sed -i 's/const out = \[ '\''default'\'' \];/const out = await dnr.getEnabledRulesets();/' uBOLite.chromium.mv3/js/ruleset-manager.js
 
 
 FROM linkding AS linkding-plus
@@ -107,8 +109,8 @@ FROM linkding AS linkding-plus
 RUN apk update && apk add nodejs npm chromium
 # install single-file from fork for now, which contains several hotfixes
 RUN npm install -g https://github.com/sissbruecker/single-file-cli/tarball/4c54b3bc704cfb3e96cec2d24854caca3df0b3b6
-# copy uBlock0
-COPY --from=ublock-build /etc/linkding/uBlock0.chromium uBlock0.chromium/
+# copy uBlock
+COPY --from=ublock-build /etc/linkding/uBOLite.chromium.mv3 uBOLite.chromium.mv3/
 # create chromium profile folder for user running background tasks
 RUN mkdir -p chromium-profile && chown -R www-data:www-data chromium-profile
 # enable snapshot support
diff --git a/docker/default.Dockerfile b/docker/default.Dockerfile
index aaa048f..629bbdd 100644
--- a/docker/default.Dockerfile
+++ b/docker/default.Dockerfile
@@ -86,18 +86,20 @@ CMD ["./bootstrap.sh"]
 FROM node:18-alpine AS ublock-build
 WORKDIR /etc/linkding
 # Install necessary tools
-RUN apk add --no-cache curl jq unzip
-# Fetch the latest release tag
-# Download the library
-# Unzip the library
-RUN TAG=$(curl -sL https://api.github.com/repos/gorhill/uBlock/releases/latest | jq -r '.tag_name') && \
-    DOWNLOAD_URL=https://github.com/gorhill/uBlock/releases/download/$TAG/uBlock0_$TAG.chromium.zip && \
-    curl -L -o uBlock0.zip $DOWNLOAD_URL && \
-    unzip uBlock0.zip
-# Patch assets.json to enable easylist-cookies by default
-RUN curl -L -o ./uBlock0.chromium/assets/thirdparties/easylist/easylist-cookies.txt https://ublockorigin.github.io/uAssets/thirdparties/easylist-cookies.txt
-RUN jq '."assets.json" |= del(.cdnURLs) | ."assets.json".contentURL = ["assets/assets.json"] | ."fanboy-cookiemonster" |= del(.off) | ."fanboy-cookiemonster".contentURL += ["assets/thirdparties/easylist/easylist-cookies.txt"]' ./uBlock0.chromium/assets/assets.json > temp.json && \
-    mv temp.json ./uBlock0.chromium/assets/assets.json
+# Download and unzip the latest uBlock Origin Lite release
+# Patch manifest to enable annoyances by default
+# Patch ruleset-manager.js to use rulesets enabled in manifest by default
+RUN apk add --no-cache curl jq unzip && \
+    TAG=$(curl -sL https://api.github.com/repos/uBlockOrigin/uBOL-home/releases/latest | jq -r '.tag_name') && \
+    DOWNLOAD_URL=https://github.com/uBlockOrigin/uBOL-home/releases/download/$TAG/$TAG.chromium.mv3.zip && \
+    echo "Downloading $DOWNLOAD_URL" && \
+    curl -L -o uBOLite.zip $DOWNLOAD_URL && \
+    unzip uBOLite.zip -d uBOLite.chromium.mv3 && \
+    rm uBOLite.zip && \
+    jq '.declarative_net_request.rule_resources |= map(if .id == "annoyances-overlays" or .id == "annoyances-cookies" or .id == "annoyances-social" or .id == "annoyances-widgets" or .id == "annoyances-others" then .enabled = true else . end)' \
+        uBOLite.chromium.mv3/manifest.json > temp.json && \
+    mv temp.json uBOLite.chromium.mv3/manifest.json && \
+    sed -i 's/const out = \[ '\''default'\'' \];/const out = await dnr.getEnabledRulesets();/' uBOLite.chromium.mv3/js/ruleset-manager.js
 
 
 FROM linkding AS linkding-plus
@@ -111,9 +113,9 @@ RUN apt-get install -y gnupg2 apt-transport-https ca-certificates && \
     apt-get update && apt-get install -y nodejs
 # install single-file from fork for now, which contains several hotfixes
 RUN npm install -g https://github.com/sissbruecker/single-file-cli/tarball/4c54b3bc704cfb3e96cec2d24854caca3df0b3b6
+# copy uBlock
+COPY --from=ublock-build /etc/linkding/uBOLite.chromium.mv3 uBOLite.chromium.mv3/
 # create chromium profile folder for user running background tasks
 RUN mkdir -p chromium-profile && chown -R www-data:www-data chromium-profile
-# copy uBlock0
-COPY --from=ublock-build /etc/linkding/uBlock0.chromium uBlock0.chromium/
 # enable snapshot support
 ENV LD_ENABLE_SNAPSHOTS=True
diff --git a/scripts/setup-ublock.sh b/scripts/setup-ublock.sh
index 415f0d6..568ea8a 100755
--- a/scripts/setup-ublock.sh
+++ b/scripts/setup-ublock.sh
@@ -1,13 +1,18 @@
-rm -rf ublock0.chromium
+rm -rf uBOLite.chromium.mv3
 
-TAG=$(curl -sL https://api.github.com/repos/gorhill/uBlock/releases/latest | jq -r '.tag_name')
-DOWNLOAD_URL=https://github.com/gorhill/uBlock/releases/download/$TAG/uBlock0_$TAG.chromium.zip
-curl -L -o uBlock0.zip $DOWNLOAD_URL
-unzip uBlock0.zip
-rm uBlock0.zip
+# Download uBlock Origin Lite
+TAG=$(curl -sL https://api.github.com/repos/uBlockOrigin/uBOL-home/releases/latest | jq -r '.tag_name')
+DOWNLOAD_URL=https://github.com/uBlockOrigin/uBOL-home/releases/download/$TAG/$TAG.chromium.mv3.zip
+echo "Downloading $DOWNLOAD_URL"
+curl -L -o uBOLite.zip $DOWNLOAD_URL
+unzip uBOLite.zip -d uBOLite.chromium.mv3
+rm uBOLite.zip
 
-curl -L -o ./uBlock0.chromium/assets/thirdparties/easylist/easylist-cookies.txt https://ublockorigin.github.io/uAssets/thirdparties/easylist-cookies.txt
-jq '."assets.json" |= del(.cdnURLs) | ."assets.json".contentURL = ["assets/assets.json"] | ."fanboy-cookiemonster" |= del(.off) | ."fanboy-cookiemonster".contentURL += ["assets/thirdparties/easylist/easylist-cookies.txt"]' ./uBlock0.chromium/assets/assets.json > temp.json
-mv temp.json ./uBlock0.chromium/assets/assets.json
+# Patch uBlock Origin Lite to respect rulesets enabled in manifest.json
+sed -i '' "s/const out = \[ 'default' \];/const out = await dnr.getEnabledRulesets();/" uBOLite.chromium.mv3/js/ruleset-manager.js
+
+# Enable annoyances rulesets in manifest.json
+jq '.declarative_net_request.rule_resources |= map(if .id == "annoyances-overlays" or .id == "annoyances-cookies" or .id == "annoyances-social" or .id == "annoyances-widgets" or .id == "annoyances-others" then .enabled = true else . end)' uBOLite.chromium.mv3/manifest.json > temp.json
+mv temp.json uBOLite.chromium.mv3/manifest.json
 
 mkdir -p chromium-profile
diff --git a/siteroot/settings/base.py b/siteroot/settings/base.py
index f7678e6..f822075 100644
--- a/siteroot/settings/base.py
+++ b/siteroot/settings/base.py
@@ -296,7 +296,7 @@ LD_SINGLEFILE_UBLOCK_OPTIONS = os.getenv(
             '--browser-arg="--headless=new"',
             '--browser-arg="--user-data-dir=./chromium-profile"',
             '--browser-arg="--no-sandbox"',
-            '--browser-arg="--load-extension=uBlock0.chromium"',
+            '--browser-arg="--load-extension=uBOLite.chromium.mv3"',
         ]
     ),
 )


Test patch:
diff --git a/bookmarks/tests/test_singlefile_service.py b/bookmarks/tests/test_singlefile_service.py
index b9b0f7a..13ca3bb 100644
--- a/bookmarks/tests/test_singlefile_service.py
+++ b/bookmarks/tests/test_singlefile_service.py
@@ -66,7 +66,7 @@ class SingleFileServiceTestCase(TestCase):
                 '--browser-arg="--headless=new"',
                 '--browser-arg="--user-data-dir=./chromium-profile"',
                 '--browser-arg="--no-sandbox"',
-                '--browser-arg="--load-extension=uBlock0.chromium"',
+                '--browser-arg="--load-extension=uBOLite.chromium.mv3"',
                 "http://example.com",
                 self.html_filepath + ".tmp",
             ]
@@ -88,7 +88,7 @@ class SingleFileServiceTestCase(TestCase):
                 '--browser-arg="--headless=new"',
                 '--browser-arg="--user-data-dir=./chromium-profile"',
                 '--browser-arg="--no-sandbox"',
-                '--browser-arg="--load-extension=uBlock0.chromium"',
+                '--browser-arg="--load-extension=uBOLite.chromium.mv3"',
                 "--some-option",
                 "some value",
                 "--another-option",