The installation prompt was only accepting lowercase 'y', causing the
script to exit when users entered uppercase 'Y'. This fix aligns the
prompt behavior with all other y/n prompts in the script by using
case-insensitive pattern matching (=~ ^[Yy]$).
Fixes issue where installation would bail after selecting Y to proceed.
Fixes JavaScript error "given browserview is not attached to the window"
that occurred when unlocking the screen after boot with password protection.
Changes to unlockScreen() function:
- Add try-catch around hidden view restoration to prevent crashes
- Ensure view is attached with addBrowserView() before setTopBrowserView()
- Add fallback to regular views if hidden view restoration fails
- Validate currentIndex is within bounds before using it
- Check views.length>0 before attempting to attach views
This ensures safe view restoration in all unlock scenarios, particularly
when unlocking immediately after boot with password protection enabled.
Key changes:
- Remove time-based lockout prompt ("Only enforce lockout during specific hours?")
- Detach all browser views when locked to prevent content visibility
- Show power menu on solid black screen (lockoutWindow) when locked
- Password protection now always active when enabled (more reliable)
Fixes:
- Users can no longer see URLs or content when password screen is active
- Pressing Ctrl+Alt+Delete shows power menu on solid screen, not over content
- All browser views completely hidden until password is entered
CRITICAL FIX: Removed lockoutActivityTime reset from markActivity()
- markActivity() was resetting lockoutActivityTime on EVERY activity
- This prevented inactivity lockout from EVER triggering
- Now lockout timer only resets when user unlocks or selects extension
ROOT CAUSE:
The markActivity() function was resetting lockoutActivityTime (line 3904):
if(enablePasswordProtection && lockoutTimeout > 0){
lockoutActivityTime = now; // ← PROBLEM
}
markActivity() is called on EVERY:
- Mouse move
- Mouse click
- Keyboard press
- Page load
- Focus change
Result: lockoutActivityTime was CONSTANTLY being reset, so lockout could
NEVER reach the configured timeout (user reported 17 minutes wasn't working).
FIX:
Removed the lockoutActivityTime reset from markActivity() entirely (line 3908).
Now lockoutActivityTime only resets when:
1. User unlocks screen (unlockScreen() function)
2. User selects time extension (showPauseDialog/showInactivityPrompt)
This is the correct, simple behavior: lockout should trigger after X minutes
of inactivity, period. If user wants to extend, they can select an extension.
USER REPORT:
- Scheduled lockout works ✓ (lock at 15:00)
- Inactivity lockout doesn't work ✗ (lock after 17 min idle)
- This fix addresses the inactivity lockout issue
SIMPLIFIED: Removed unnecessary complexity added in v0.9.5-7 and v0.9.5-8.
The simple fix was just to stop resetting the timer on every activity.
CRITICAL FIX: Extensions now properly reset lockout activity timer
- Pause button extensions now reset lockoutActivityTime when selected
- Manual site timeout extensions now reset lockoutActivityTime when selected
- Prevents lockout from counting idle time accumulated BEFORE extension
- Lockout timer now truly starts fresh when user selects an extension
ROOT CAUSE (v0.9.5-7 was incomplete):
In v0.9.5-7, I added code to checkLockoutTimer() to SKIP lockout checks during
active extensions. This prevented lockout from triggering during the extension
period. However, the extension handlers themselves didn't reset lockoutActivityTime.
TWO PLACES WERE MISSING lockoutActivityTime reset:
1. showInactivityPrompt() - Manual site timeout extensions (line 4632)
When user selects "15 minutes" on manual site inactivity prompt:
✓ Set inactivityExtensionUntil = now + 15min
✓ Set lastUserInteraction = now
✓ Set siteStartTime = now
✗ Did NOT set lockoutActivityTime = now
2. showPauseDialog() - Pause button extensions (line 4680)
When user clicks pause button and selects "15 minutes":
✓ Set inactivityExtensionUntil = now + 15min
✓ Set lastUserInteraction = now
✓ Set siteStartTime = now
✗ Did NOT set lockoutActivityTime = now
BROKEN SCENARIO IN v0.9.5-7:
- Lockout configured for 30 minutes of inactivity
- User is idle for 10 minutes
- User clicks "15 minutes" extension
- lockoutActivityTime still shows 10 minutes ago (NOT reset)
- Extension blocks lockout for 15 minutes (v0.9.5-7 fix working)
- After 15 minutes, extension expires
- v0.9.5-7 code resets lockoutActivityTime to now
- Lockout would happen 30 minutes later
The problem: This means lockout NEVER enforced the configured timeout if
users kept selecting extensions, because each extension expiration reset
the lockout timer.
FIX IN v0.9.5-8:
Added lockoutActivityTime = now to BOTH extension handlers:
- Lines 4637-4641: Manual site inactivity prompt extension handler
- Lines 4684-4688: Pause button extension handler
NEW BEHAVIOR:
- User idle for 10 minutes
- User clicks "15 minutes" extension
- lockoutActivityTime = now (RESET on extension selection)
- User is now considered "active" (selected extension = user interaction)
- Extension blocks lockout for 15 minutes
- After 15 minutes, lockoutActivityTime shows 15 minutes ago
- Lockout happens 30 minutes after extension selected (at 15 + 30 = 45 min total)
This is more intuitive: selecting an extension is a user interaction that
proves the user is present, so lockout timer should start fresh.
Includes all fixes from v0.9.5-7 (checkLockoutTimer respects extensions)
CRITICAL FIX: Inactivity lockout now respects time extensions
- Lockout timer was completely ignoring pause button extensions
- Lockout timer was ignoring manual site timeout extensions
- Added inactivityExtensionUntil check to checkLockoutTimer() function
- Time extensions now properly prevent BOTH site timeout AND lockout
- When extension expires, lockout timer resets (doesn't trigger immediately)
FIXED: Manual sites (duration: 0) now fully support time extensions
- Pause button extensions now work on manual sites
- Manual site timeout extensions now prevent lockout
- Extensions apply to both rotation blocking AND lockout prevention
ROOT CAUSE:
The checkLockoutTimer() function (line 4061) only checked:
- lockoutActivityTime vs lockoutTimeout
- Did NOT check inactivityExtensionUntil
This meant when a user clicked "15 minutes" on pause button:
✓ Site rotation/timeout was blocked (lines 4317, 4375 checked extension)
✗ Inactivity lockout still triggered after configured time
EXAMPLE SCENARIO THAT WAS BROKEN:
- Manual site with 2 min inactivity timeout to return home
- Lockout after 5 minutes of inactivity
- User idle for 1m 50s, clicks "15 minutes" extension
- Expected: Can stay for 15 more minutes
- Actual v0.9.5-6:
* Home return prompt blocked ✓
* Lockout happens at 5 min idle ✗
- Fixed v0.9.5-7:
* Home return prompt blocked ✓
* Lockout also blocked for 15 min ✓
FIX (lines 4083-4100):
Now checkLockoutTimer() checks inactivityExtensionUntil FIRST:
1. If within extension period: return early (skip lockout check)
2. If extension just expired: reset lockoutActivityTime (prevent immediate trigger)
3. Then check normal lockout timeout
This matches the pattern used in rotation (line 4317) and home return (line 4375).
Includes all fixes from v0.9.5-6 (boot password sequence, limited power menu)
CRITICAL SECURITY FIX#1: Boot password now required BEFORE showing websites
- Password screen now appears IMMEDIATELY on boot (no website flash)
- Websites and rotation timer only start AFTER successful password entry
- Root cause: attachView() was called before checking boot flag
- Fix: Reordered code to check boot flag FIRST, only call attachView() if no boot
- unlockScreen() now starts master timer when unlocking from boot password
CRITICAL SECURITY FIX#2: Limited power menu when locked out
- Ctrl+Alt+Del when locked now shows LIMITED menu: Shutdown/Restart/Cancel
- NO Reload option available when locked (prevents bypass)
- Full menu (with Reload) only available when unlocked
- Still allows emergency shutdown/restart without password
- Message clearly indicates "System is locked. Limited options available."
ROOT CAUSE OF BOOT PASSWORD BYPASS:
In v0.9.5-5, the code sequence was:
1. attachView(startIndex) - shows website
2. Check boot flag - if exists, show password screen
This meant users saw the website for ~1 second, then password screen appeared.
Pressing Ctrl+Alt+Del at that moment would reload and bypass the password.
NEW SEQUENCE in v0.9.5-6:
1. Check boot flag FIRST
2. If boot flag exists: show password screen, DON'T load websites
3. If no boot flag: load websites normally
4. When password entered: attachView() and startMasterTimer()
Includes all fixes from v0.9.5-5 and v0.9.5-4
CRITICAL SECURITY FIX:
- Fixed Ctrl+Alt+Del bypassing boot password requirement
* Added isLockedOut check to showPowerMenu() function
* Power menu (Shutdown/Restart/Reload) now blocked when system is locked out
* Prevents bypassing boot password via Reload option
* Also prevents bypassing inactivity lockout and time-based lockout
ROOT CAUSE:
The showPowerMenu() function was missing the isLockedOut check that other
navigation functions (nextTab, prevTab) already had. This allowed users to
press Ctrl+Alt+Del during boot password screen, select "Reload", and bypass
the password requirement entirely.
NAVIGATION TROUBLESHOOTING:
Added troubleshooting notes for users experiencing navigation issues:
- Check config.json for hidden sites (duration: -1)
- Hidden sites don't count toward navigation
- Need at least 2 visible sites for Ctrl+Tab/swipe to work
Includes all fixes from v0.9.5-4 (polkit restrictions, X server hardening,
autostart compatibility, xbindkeys fixes)
This was the root cause of extensions not working. When user clicked
extension buttons (15 min, 30 min, etc.), that click triggered markActivity()
which immediately cleared the extension that was just set.
Now extensions work correctly - they only expire when:
- Time runs out naturally
- User explicitly goes home
- User cancels the extension
This fixes:
- Pause button extensions not working (rotating after 1 min)
- Manual site timeout extensions not working (prompt after 1 min)
- Both rotation and inactivity timer extensions
This release fixes multiple critical bugs reported in v0.9.5-1:
## Configuration Persistence Fixes
- **CRITICAL**: Fixed sites being wiped when editing password/pause/OSK settings
- Added load_existing_config() function to load all settings before any menu
- Now called before configure_optional_features and configure_password_protection
- Prevents empty URLS/DURS arrays from overwriting existing sites in save_config
- **Fixed password protection not being saved on reboot**
- Settings now properly persist through load_existing_config function
- All password protection variables properly loaded from config.json
- **Fixed sites not being saved on reboot**
- Configuration persistence issue resolved with load_existing_config
## Timing & Extension Fixes (main.js)
- **Fixed time extension rotating to wrong site**
- Added checks to prevent rotation while pause dialog is open
- Added checks to prevent rotation while inactivity prompt is open
- Extension is now applied to the current site, not the next one
- **Fixed pause not working correctly**
- Pause dialog no longer allows rotation during user selection
- Extension properly blocks rotation until time expires
- **Fixed manual site timeout popup appearing after 1 minute**
- Fixed extension expiration to reset lastUserInteraction
- Prevents prompt from showing immediately after extension expires
- Added proper checks to prevent duplicate prompts
## User Experience Improvements
- **Added cancel/exit option to menus**
- configure_optional_features now asks "Save these changes?"
- configure_password_protection now asks "Save these changes?"
- Users can discard changes by answering "no"
- **Added comprehensive settings display**
- show_current_config now displays all sites with [HOME] marker
- Shows home URL and inactivity timeout
- Shows optional features status (pause/keyboard buttons)
- Shows complete password protection configuration
- Shows lockout timeout, lock time, active hours, and boot password
## Version Updates
- Bumped SCRIPT_VERSION to 0.9.5-2
- Bumped main.js VERSION to 0.9.5-2
All reported issues from 0.9.5-1 have been addressed.
New Features:
- Time-based session lockout: Automatically lock at a specific time daily
- Active hours for lockout: Only enforce timeout during configured hours
- Password on boot: Require password when system powers on/reboots
- Enhanced lockout timeout: Now respects active hours configuration
Configuration Options:
- lockoutAtTime: Time to auto-lock (e.g., "17:00")
- lockoutActiveStart/End: Time range for lockout enforcement
- requirePasswordOnBoot: Boolean to require password on system boot
Technical Changes:
- Updated configure_password_protection() with new prompts
- Added lockout time validation (HH:MM format)
- Enhanced main.js with isWithinActiveHours() and checkScheduledLockTime()
- Added boot flag creation in openbox autostart
- Updated config.json schema with new fields
The session timeout (inactivityTimeout) continues to work as before,
returning to home page after inactivity. The lockout timeout provides
an additional security layer with password protection.
- Fixed missing closing brace in keyboard auto-close section
- Removed duplicate line in showKeyboardIcon function
- Corrects SyntaxError: missing ) after argument list at line 441
Based on v0.9.2-6 (includes enhanced Electron update tool)
Version 0.9.4 introduces configurable optional features and security:
New Features:
- Optional pause button: Can be disabled during install/rerun
* Disables functionality entirely, not just hides the UI
* Configured in Core Settings menu (option 7)
- Optional keyboard button: Can be disabled during install/rerun
* Disables on-screen keyboard functionality completely
* Configured in Core Settings menu (option 7)
- Password protection with session lockout:
* Customizable lockout timeout (in minutes of inactivity)
* Blank screen during lockout with no interaction allowed
* Password required to unlock after timeout
* Password required after display schedule wake-up
* SHA-256 password hashing for security
* Option to only require password after display wake (0 minute timeout)
Configuration:
- New configure_optional_features() function for pause/keyboard buttons
- New configure_password_protection() function for security setup
- Added to Core Settings menu (options 7 & 8)
- All settings saved to config.json and loaded on startup
Implementation:
- Main.js: Password lockout window with blank screen
- Main.js: Lockout timer check in master timer loop
- Main.js: Display wake flag detection (.display-wake file)
- Main.js: Conditional pause button visibility based on config
- Preload.js: Conditional keyboard button based on config
- Display-on script: Creates flag file to trigger password requirement
All features are configurable on first install or by rerunning the script.
Fixed two critical issues preventing Electron update from completing:
1. cd permission denied error
Problem: Script tried to `cd /home/kiosk/kiosk-app` which failed with
"Permission denied" because the directory has restricted permissions (drwxr-x---)
and the regular user can't enter it.
Fix: Use `sudo -u kiosk bash -c "cd '/home/kiosk/kiosk-app' && npm install ..."`
instead of separate cd + npm commands. This runs both commands as the kiosk
user in a single bash session, avoiding the permission issue.
2. Wrong service name (kiosk vs lightdm)
Problem: Scripts tried to stop/start "kiosk" service which doesn't exist on
the user's system. Their kiosk runs under lightdm service.
Fix: Changed all references from:
- `systemctl stop/start kiosk` → `systemctl stop/start lightdm`
- "Restart kiosk service" → "Restart kiosk display"
- `journalctl -u kiosk` → `journalctl -u lightdm`
Additional fixes:
- Updated file checks: `[ -d ]` → `sudo test -d` for restricted directories
- Applied fixes to both update paths: successful install and failure/restore
- Updated both update_electron.sh and install_kiosk_0.9.2-6.sh
Changes in both scripts:
- update_electron() function: removed cd, added bash -c wrapper, changed service name
- Backup restore paths: same fixes applied
- Success path: updated restart prompts and service checks
- Failure path: fixed restore process with proper directory access
The update should now complete successfully without permission errors.
Fixed two issues preventing the Electron update from working properly:
1. Log messages appearing in version output
- get_latest_electron_version() was outputting log messages to stdout
- These messages were being captured along with the version number
- Result: "Target version: [INFO] Fetching...39.2.3" in output
- Fix: Redirect log_info and log_error to stderr with >&2
- Now only the version number is captured in the variable
2. Backup function permission errors
- stat command needed sudo to read owner of restricted directories
- File checks [ -f ] couldn't access files in drwxr-x--- directories
- mkdir failed with "cannot create directory '/home/kiosk': Permission denied"
- Fix: Use sudo for all file operations in create_backup():
* sudo stat -c '%U' to get directory owner
* sudo test -f/d for file/directory checks
* sudo -u owner for mkdir, cp, and file writes
Changes in both update_electron.sh and install_kiosk_0.9.2-6.sh:
- get_latest_electron_version functions: Added >&2 to log statements
- create_backup functions: Added sudo to stat and all file checks
- Ensures backup works with restricted /home/kiosk permissions
The update process should now complete successfully without permission errors
or garbled version output.
The scripts were failing to find the kiosk installation at /home/kiosk/kiosk-app
because the /home/kiosk directory has restricted permissions (drwxr-x---),
preventing regular users from reading it.
Changes in both update_electron.sh and install_kiosk_0.9.2-6.sh:
1. Updated find_kiosk_dir() to use sudo for all file checks
- sudo test -f for checking if main.js exists
- Prevents "permission denied" errors on restricted directories
2. Added Method 4: Detect from running electron process
- Parses ps output to find electron executable path
- Extracts app directory from the path
- Provides fallback when directory searches fail
3. Updated get_current_electron_version functions
- Use sudo test -f to check if package.json exists
- Use sudo grep to read package.json and get version
- Ensures version detection works with restricted permissions
4. Fixed directory existence checks
- Use sudo test -d for checking kiosk directory
These changes allow the scripts to:
- Find kiosk installations in directories with restricted permissions
- Detect installations even when run as a regular user
- Work correctly with the standard /home/kiosk setup (drwxr-x---)
- Provide better fallback detection using running processes
The scripts will now prompt for sudo password when needed to check
for files in restricted directories, then continue normally.
Changed the script to run as a regular user instead of requiring sudo.
The script now:
- Checks that it's NOT being run as root (prevents sudo usage)
- Uses sudo for individual commands that need elevated privileges
- Prompts for sudo password only when needed
Changes:
- Removed EUID check that required running with sudo
- Added check to prevent running as root
- Added sudo to backup operations (mkdir, cp, file writes)
- All systemctl and npm install commands already use sudo appropriately
This matches the behavior of install_kiosk scripts which should be run
as a regular user, not with sudo.
Usage: ./update_electron.sh (not sudo ./update_electron.sh)
This new version of the install script includes a completely rewritten
manual Electron update tool that fixes all the issues with the previous version:
NEW FEATURES:
- Smart installation detection across multiple locations
- Verifies Electron is actually running (not just installed)
- Gets current version from both package.json and node_modules
- Fetches latest stable version from npm with multiple fallback methods
- Clear version comparison display (current vs latest)
- Breaking changes warning with direct links to Electron documentation
- Automatic backup creation before any changes
- Provides clear restore instructions
- Multiple user confirmation prompts before making changes
- Automatic rollback if update fails
- Fixes chrome-sandbox permissions after installation
- Manages kiosk service stop/start automatically
FIXES:
- No more "no electron app found" errors
- No more "script just bails" - proper error handling throughout
- Proper detection of running Electron instances
- Network failure handling with multiple fallback methods
- Clear feedback at every step of the process
The enhanced update tool is accessible from:
Advanced Menu → Manual Electron Update
Version updated from 0.9.2 to 0.9.2-6 to reflect the enhancement.
This script addresses issues with the manual Electron update process by:
- Detecting kiosk installation across multiple methods (user home, systemd service)
- Checking if Electron is actually running (not just installed)
- Getting current Electron version from both package.json and node_modules
- Fetching latest stable Electron version from npm registry with fallbacks
- Displaying clear version comparison (current vs latest)
- Warning users to check for breaking changes with links to documentation
- Creating automatic backups of package.json, package-lock.json, and version info
- Providing clear restore instructions if something goes wrong
- Requiring user confirmation at multiple steps before making changes
- Automatically attempting rollback if the update fails
- Fixing chrome-sandbox permissions after installation
- Managing kiosk service stop/start around the update
The script handles edge cases like:
- Missing or moved installations
- Network failures when fetching versions
- Failed npm installations with automatic recovery
- Permission issues with proper sudo user handling
Users can now safely update Electron with confidence that they can restore
if needed, and with clear visibility into what versions are being used.