forked from gsalucci/firefox-profiles-to-ram
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathbrowser-to-ram-utils
More file actions
executable file
·209 lines (170 loc) · 5.93 KB
/
browser-to-ram-utils
File metadata and controls
executable file
·209 lines (170 loc) · 5.93 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
#!/bin/bash
# Browser to RAM Utils
# Handles Firefox profile synchronization to/from RAM (tmpfs)
set -euo pipefail
# --- Configuration ---
USER=$(id -un)
PROFILES_HOME="/home/$USER/.config/mozilla/firefox"
PROFILES_HOME_RAM="/dev/shm/$USER/browser-profiles"
PROFILES_INI="$PROFILES_HOME/profiles.ini"
# --- Logging ---
log() {
local level=$1
local message=$2
# Print to stderr for console visibility
echo "[$level] $message" >&2
# Log to systemd journal
# We use 'cat' to pipe to systemd-cat to avoid issues if systemd-cat is missing or fails
if command -v systemd-cat >/dev/null 2>&1; then
echo "$message" | systemd-cat -t "browser-to-ram" -p "$level"
fi
}
log_info() { log "info" "$1"; }
log_err() { log "err" "$1"; }
# --- Helper Functions ---
# Get list of profile paths from profiles.ini
get_profiles() {
if [[ ! -f "$PROFILES_INI" ]]; then
log_err "profiles.ini not found at $PROFILES_INI"
exit 1
fi
# Parse profiles.ini to find Path= lines
# We handle both relative and absolute paths
# This is a simplified parser that assumes standard INI format
# Grep all lines starting with Path=, remove 'Path=', then process
grep "^Path=" "$PROFILES_INI" | cut -d'=' -f2 | while read -r path; do
# Trim whitespace (just in case)
path=$(echo "$path" | xargs)
if [[ "$path" == /* ]]; then
echo "$path"
else
echo "$PROFILES_HOME/$path"
fi
done
}
kill_firefox() {
log_info "Stopping Firefox..."
pkill -u "$USER" -TERM firefox || true
# Wait for it to close
for i in {1..10}; do
if ! pgrep -u "$USER" firefox > /dev/null; then
break
fi
sleep 1
done
# Force kill if necessary
if pgrep -u "$USER" firefox > /dev/null; then
log_info "Firefox still running, force killing..."
pkill -u "$USER" -KILL firefox || true
fi
}
# --- Main Actions ---
do_init() {
log_info "Starting initialization..."
# We need to kill firefox once before processing any profile
kill_firefox
get_profiles | while read -r source_path; do
local profile_dirname=$(basename "$source_path")
local disk_path="${source_path}.bak"
local ram_path="$PROFILES_HOME_RAM/$profile_dirname"
# Check if already initialized
if [[ -L "$source_path" ]]; then
log_info "Profile $profile_dirname is already a symlink. Skipping."
continue
fi
if [[ -d "$disk_path" ]]; then
log_info "Backup $disk_path already exists. Skipping to avoid data loss."
continue
fi
log_info "Initializing profile: $profile_dirname"
# 1. Sync source to RAM
mkdir -p "$(dirname "$ram_path")"
log_info "Syncing $source_path to $ram_path..."
if ! rsync -a "$source_path/" "$ram_path/"; then
log_err "Failed to sync to RAM. Aborting for $profile_dirname"
continue
fi
# 2. Rename source to disk (backup)
log_info "Moving source to backup..."
if ! mv "$source_path" "$disk_path"; then
log_err "Failed to move source to backup. Rolling back RAM..."
rm -rf "$ram_path"
continue
fi
# 3. Create symlink
log_info "Creating symlink..."
if ! ln -s "$ram_path" "$source_path"; then
log_err "Failed to create symlink. Rolling back..."
mv "$disk_path" "$source_path"
rm -rf "$ram_path"
continue
fi
log_info "Profile $profile_dirname initialized and loaded."
done
}
do_load() {
log_info "Loading profiles to RAM..."
get_profiles | while read -r source_path; do
# source_path is the location where firefox expects the profile (now a symlink)
local profile_dirname=$(basename "$source_path")
local disk_path="${source_path}.bak"
local ram_path="$PROFILES_HOME_RAM/$profile_dirname"
if [[ ! -L "$source_path" ]] || [[ ! -d "$disk_path" ]]; then
log_err "Profile $profile_dirname uninitialized (not a symlink or backup missing). Ignoring."
continue
fi
log_info "Loading $profile_dirname..."
# Create RAM folder
mkdir -p "$ram_path"
# Sync disk to RAM
# We use rsync to maintain permissions and attributes
if rsync -a --delete "$disk_path/" "$ram_path/"; then
log_info "Profile $profile_dirname loaded."
else
log_err "Failed to load profile $profile_dirname."
fi
done
}
do_store() {
log_info "Storing profiles to disk..."
# Kill Firefox before storing to ensure DBs are unlocked and consistent
kill_firefox
get_profiles | while read -r source_path; do
local profile_dirname=$(basename "$source_path")
local disk_path="${source_path}.bak"
local ram_path="$PROFILES_HOME_RAM/$profile_dirname"
if [[ ! -L "$source_path" ]] || [[ ! -d "$disk_path" ]]; then
log_err "Profile $profile_dirname uninitialized. Ignoring."
continue
fi
# CRITICAL CHECK: Ensure RAM has content or at least exists.
if [[ ! -d "$ram_path" ]]; then
log_err "RAM path $ram_path does not exist. Cannot store. Is the profile loaded?"
continue
fi
log_info "Storing $profile_dirname..."
# Sync RAM to disk
# Overwrite targets, delete extraneous files in backup
if rsync -a --delete "$ram_path/" "$disk_path/"; then
log_info "Profile $profile_dirname stored."
else
log_err "Failed to store profile $profile_dirname."
fi
done
}
# --- Dispatcher ---
case "${1:-init}" in
init)
do_init
;;
load)
do_load
;;
store)
do_store
;;
*)
echo "Usage: $0 {init|load|store}"
exit 1
;;
esac