diff --git a/docker/entrypoint.sh b/docker/entrypoint.sh index d85df72..a96488a 100755 --- a/docker/entrypoint.sh +++ b/docker/entrypoint.sh @@ -8,6 +8,7 @@ DISPLAY_NUM="${VNC_DISPLAY_NUM:-99}" VNC_PORT="${VNC_PORT:-5900}" NOVNC_PORT="${NOVNC_PORT:-6080}" GEOMETRY="${SCREEN_GEOMETRY:-1280x800x24}" +BROWSER_SESSION_DIR="${BROWSER_SESSION_DIR:-/app/data/browser-session}" export DISPLAY=":${DISPLAY_NUM}" # noVNC ships under different paths depending on the distro; find the web root once. @@ -29,6 +30,15 @@ fi # to bind to the display and the bot starts up with no X server. rm -f "/tmp/.X${DISPLAY_NUM}-lock" "/tmp/.X11-unix/X${DISPLAY_NUM}" 2>/dev/null || true +# Persistent profiles retain Chromium's singleton artifacts when a container +# is replaced before Chromium exits cleanly. Remove only those locks; cookies, +# local storage, and the rest of the authenticated profile remain untouched. +rm -f \ + "${BROWSER_SESSION_DIR}/SingletonLock" \ + "${BROWSER_SESSION_DIR}/SingletonSocket" \ + "${BROWSER_SESSION_DIR}/SingletonCookie" \ + 2>/dev/null || true + echo "[entrypoint] starting Xvfb on ${DISPLAY} (${GEOMETRY})" Xvfb "${DISPLAY}" -screen 0 "${GEOMETRY}" -ac +extension RANDR & XVFB_PID=$! diff --git a/tests/vnc-entrypoint.test.ts b/tests/vnc-entrypoint.test.ts index 4cf752f..23623d9 100644 --- a/tests/vnc-entrypoint.test.ts +++ b/tests/vnc-entrypoint.test.ts @@ -13,4 +13,13 @@ describe('VNC container entrypoint', () => { script.indexOf('starting noVNC'), ); }); + + it('removes only stale Chromium singleton artifacts before launching the bot', () => { + const script = fs.readFileSync(path.resolve('docker/entrypoint.sh'), 'utf8'); + + expect(script).toContain('"${BROWSER_SESSION_DIR}/SingletonLock"'); + expect(script).toContain('"${BROWSER_SESSION_DIR}/SingletonSocket"'); + expect(script).toContain('"${BROWSER_SESSION_DIR}/SingletonCookie"'); + expect(script.indexOf('SingletonLock')).toBeLessThan(script.indexOf('launching bot')); + }); });