ae841ceedb
Cinco funciones nuevas (dominio browser, grupo navegator) que cierran los gaps de gestión de perfiles, más un pipeline que las orquesta: - backup_chrome_bookmarks / restore_chrome_bookmarks: backup y restore de los archivos Bookmarks (copia byte a byte verbatim para preservar el checksum interno; en Chromium 148 los bookmarks no están bajo el super_mac de Secure Preferences). Guard por user-data-dir (no global). - delete_chrome_profile: borra la carpeta del perfil + limpia su entrada en Local State (info_cache, profiles_order, last_active_profiles, last_used). - create_chrome_profile: lanza chromium headless (vía systemd-run) para que la managed policy instale la whitelist de extensiones, y asigna el nombre legible en Local State. Mata todo el árbol de chromium del udd antes de editar Local State (los hijos zygote/gpu no repiten --user-data-dir pero referencian la ruta). - list_chrome_profile_extensions (Go): lista extensiones de un perfil con ID/name/version/location/enabled/fromPolicy. 7 unit tests. - reset_chrome_profiles (pipeline): backup -> cerrar chromium -> delete -> create -> restore -> verify. Destructivo (--yes), --dry-run seguro. Validado: unit tests Go verdes, backup/restore byte-idéntico, delete limpia Local State, create instala la forcelist global (uBlock + web_proxy) en perfiles nuevos.
140 lines
5.8 KiB
Bash
140 lines
5.8 KiB
Bash
#!/usr/bin/env bash
|
|
# backup_chrome_bookmarks — copia byte a byte los archivos Bookmarks de perfiles
|
|
# Chrome/Chromium a un directorio de backup con timestamp. Preserva el checksum
|
|
# interno del archivo sin parsear ni reserializar el JSON.
|
|
|
|
set -euo pipefail
|
|
|
|
backup_chrome_bookmarks() {
|
|
# ── defaults ──────────────────────────────────────────────────────────────
|
|
local _user_data_dir=""
|
|
local _profiles=()
|
|
local _backup_dir="${HOME}/.local/share/web_scraping/bookmarks-backups"
|
|
local _dry_run=0
|
|
|
|
# ── parse args ─────────────────────────────────────────────────────────────
|
|
_usage() {
|
|
cat >&2 <<'EOF'
|
|
Usage: backup_chrome_bookmarks --user-data-dir <dir> [--profile <name>]...
|
|
[--backup-dir <dir>] [--dry-run]
|
|
|
|
--user-data-dir (obligatorio) Raíz de perfiles de Chrome/Chromium.
|
|
Ej: ~/.config/chromium-cdp
|
|
--profile <name> Nombre de carpeta de perfil a respaldar (repetible).
|
|
Si no se pasa ninguno → respalda TODOS los perfiles con
|
|
un archivo Bookmarks (excluye System Profile).
|
|
--backup-dir <dir> Directorio raíz para backups.
|
|
Default: ~/.local/share/web_scraping/bookmarks-backups
|
|
--dry-run Muestra qué copiaría sin tocar nada.
|
|
|
|
Exit codes:
|
|
0 éxito (o dry-run completado)
|
|
1 error de argumento o validación
|
|
EOF
|
|
return 1
|
|
}
|
|
|
|
while [[ $# -gt 0 ]]; do
|
|
case "$1" in
|
|
--user-data-dir) _user_data_dir="$2"; shift 2 ;;
|
|
--profile) _profiles+=("$2"); shift 2 ;;
|
|
--backup-dir) _backup_dir="$2"; shift 2 ;;
|
|
--dry-run) _dry_run=1; shift ;;
|
|
-h|--help) _usage; return 0 ;;
|
|
*) echo "backup_chrome_bookmarks: argumento desconocido: $1" >&2; return 1 ;;
|
|
esac
|
|
done
|
|
|
|
# ── validaciones ──────────────────────────────────────────────────────────
|
|
if [[ -z "$_user_data_dir" ]]; then
|
|
echo "backup_chrome_bookmarks: --user-data-dir es obligatorio" >&2
|
|
return 1
|
|
fi
|
|
|
|
if [[ ! -d "$_user_data_dir" ]]; then
|
|
echo "backup_chrome_bookmarks: directorio no encontrado: ${_user_data_dir}" >&2
|
|
return 1
|
|
fi
|
|
|
|
# ── descubrir perfiles si no se pasó ninguno ───────────────────────────────
|
|
if [[ ${#_profiles[@]} -eq 0 ]]; then
|
|
local _candidate
|
|
while IFS= read -r -d '' _candidate; do
|
|
local _pname
|
|
_pname="$(basename "$_candidate")"
|
|
# Excluir System Profile (perfil interno de Chromium sin datos de usuario)
|
|
if [[ "$_pname" == "System Profile" ]]; then
|
|
continue
|
|
fi
|
|
if [[ -f "${_candidate}/Bookmarks" ]]; then
|
|
_profiles+=("$_pname")
|
|
fi
|
|
done < <(find "$_user_data_dir" -mindepth 1 -maxdepth 1 -type d -print0 | sort -z)
|
|
fi
|
|
|
|
if [[ ${#_profiles[@]} -eq 0 ]]; then
|
|
echo "backup_chrome_bookmarks: no se encontraron perfiles con archivo Bookmarks en: ${_user_data_dir}" >&2
|
|
return 1
|
|
fi
|
|
|
|
# ── timestamp único para este backup ──────────────────────────────────────
|
|
local _ts
|
|
_ts="$(date +%Y%m%dT%H%M%S)"
|
|
|
|
# ── procesar perfiles ─────────────────────────────────────────────────────
|
|
# Construir el array de resultados JSON manualmente (sin jq ni python3)
|
|
local _results="["
|
|
local _first=1
|
|
local _profile
|
|
|
|
for _profile in "${_profiles[@]}"; do
|
|
local _src="${_user_data_dir}/${_profile}/Bookmarks"
|
|
|
|
# Si el perfil no tiene Bookmarks, se omite sin error
|
|
if [[ ! -f "$_src" ]]; then
|
|
continue
|
|
fi
|
|
|
|
local _dst="${_backup_dir}/${_ts}/${_profile}/Bookmarks"
|
|
local _bytes
|
|
_bytes="$(wc -c < "$_src")"
|
|
|
|
if [[ $_dry_run -eq 1 ]]; then
|
|
echo "backup_chrome_bookmarks: [dry-run] cp -p \"${_src}\" -> \"${_dst}\" (${_bytes} bytes)" >&2
|
|
else
|
|
local _dst_dir
|
|
_dst_dir="$(dirname "$_dst")"
|
|
mkdir -p "$_dst_dir"
|
|
cp -p "$_src" "$_dst"
|
|
fi
|
|
|
|
# Escapar comillas dobles en el path por si acaso
|
|
local _src_esc="${_src//\"/\\\"}"
|
|
local _dst_esc="${_dst//\"/\\\"}"
|
|
local _profile_esc="${_profile//\"/\\\"}"
|
|
|
|
local _entry
|
|
_entry="$(printf '{"profile":"%s","src":"%s","dst":"%s","bytes":%s}' \
|
|
"$_profile_esc" "$_src_esc" "$_dst_esc" "$_bytes")"
|
|
|
|
if [[ $_first -eq 1 ]]; then
|
|
_results+="$_entry"
|
|
_first=0
|
|
else
|
|
_results+=",${_entry}"
|
|
fi
|
|
done
|
|
|
|
_results+="]"
|
|
|
|
# ── emitir resultado JSON ──────────────────────────────────────────────────
|
|
local _backup_dir_esc="${_backup_dir//\"/\\\"}"
|
|
printf '{"backup_dir":"%s","ts":"%s","profiles":%s}\n' \
|
|
"$_backup_dir_esc" "$_ts" "$_results"
|
|
}
|
|
|
|
# ── auto-ejecución ────────────────────────────────────────────────────────────
|
|
if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then
|
|
backup_chrome_bookmarks "$@"
|
|
fi
|