fix: reuse browser, harden session restore without URL clash (v2.0.27)
Some checks failed
技能自动化发布 / release (push) Has been cancelled

This commit is contained in:
2026-09-15 11:46:08 +08:00
parent 44eafff757
commit b93b2ea36e
5 changed files with 160 additions and 22 deletions

View File

@@ -3,11 +3,10 @@
from __future__ import annotations
import json
import logging
import os
from typing import Any, Dict
logger = logging.getLogger(__name__)
from util.logging_config import get_skill_logger
RESTORE_CONTINUE_WHERE_LEFT_OFF = 1
@@ -16,8 +15,60 @@ def preferences_path(profile_dir: str) -> str:
return os.path.join(os.path.abspath(profile_dir), "Default", "Preferences")
def local_state_path(profile_dir: str) -> str:
return os.path.join(os.path.abspath(profile_dir), "Local State")
def _patch_preferences_dict(data: Dict[str, Any]) -> Dict[str, Any]:
before = int((data.get("session") or {}).get("restore_on_startup") or 0)
exit_before = str((data.get("profile") or {}).get("exit_type") or "")
session = data.setdefault("session", {})
session["restore_on_startup"] = RESTORE_CONTINUE_WHERE_LEFT_OFF
session.pop("startup_urls", None)
profile = data.setdefault("profile", {})
if str(profile.get("exit_type") or "").lower() == "crashed":
profile["exit_type"] = "Normal"
profile["exited_cleanly"] = True
browser = data.setdefault("browser", {})
browser["has_seen_welcome_page"] = True
browser["check_default_browser"] = False
return {"restore_before": before, "exit_type_before": exit_before}
def _patch_local_state(profile_dir: str, log) -> Dict[str, Any]:
path = local_state_path(profile_dir)
if not os.path.isfile(path):
return {"ok": True, "skipped": True, "path": path}
try:
with open(path, "r", encoding="utf-8") as fh:
data = json.load(fh)
except Exception as exc:
log.warning("chrome_local_state_read_failed path=%s err=%s", path, exc)
return {"ok": False, "path": path, "error": str(exc)}
profile = data.setdefault("profile", {})
info = profile.setdefault("info_cache", {}).setdefault("Default", {})
info["active_time"] = float(info.get("active_time") or 0.0) or 1.0
exited = profile.get("exited_cleanly", True)
profile["exited_cleanly"] = True
try:
with open(path, "w", encoding="utf-8") as fh:
json.dump(data, fh, ensure_ascii=False, separators=(",", ":"))
except Exception as exc:
log.warning("chrome_local_state_write_failed path=%s err=%s", path, exc)
return {"ok": False, "path": path, "error": str(exc), "exited_cleanly_before": exited}
log.info("chrome_local_state_patched path=%s exited_cleanly %s->True", path, exited)
return {"ok": True, "path": path, "exited_cleanly_before": exited}
def ensure_session_restore(profile_dir: str) -> Dict[str, Any]:
"""启动浏览器前写入 session.restore_on_startup=1;Crashed → Normal。"""
"""启动浏览器前写入 session.restore_on_startup=1;清 startup_urls;Local State 干净退出。"""
log = get_skill_logger()
profile_abs = os.path.abspath(profile_dir)
prefs = preferences_path(profile_abs)
os.makedirs(os.path.dirname(prefs), exist_ok=True)
@@ -28,24 +79,18 @@ def ensure_session_restore(profile_dir: str) -> Dict[str, Any]:
with open(prefs, "r", encoding="utf-8") as fh:
data = json.load(fh)
except Exception:
logger.exception("chrome_prefs_read_failed path=%s", prefs)
log.exception("chrome_prefs_read_failed path=%s", prefs)
data = {}
before = int((data.get("session") or {}).get("restore_on_startup") or 0)
exit_before = str((data.get("profile") or {}).get("exit_type") or "")
session = data.setdefault("session", {})
session["restore_on_startup"] = RESTORE_CONTINUE_WHERE_LEFT_OFF
profile = data.setdefault("profile", {})
if str(profile.get("exit_type") or "").lower() == "crashed":
profile["exit_type"] = "Normal"
meta = _patch_preferences_dict(data)
before = int(meta["restore_before"])
exit_before = str(meta["exit_type_before"] or "")
try:
with open(prefs, "w", encoding="utf-8") as fh:
json.dump(data, fh, ensure_ascii=False, separators=(",", ":"))
except Exception as exc:
logger.warning("chrome_prefs_write_failed path=%s err=%s", prefs, exc)
log.warning("chrome_prefs_write_failed path=%s err=%s", prefs, exc)
return {
"ok": False,
"path": prefs,
@@ -58,9 +103,10 @@ def ensure_session_restore(profile_dir: str) -> Dict[str, Any]:
after = int((data.get("session") or {}).get("restore_on_startup") or 0)
exit_after = str((data.get("profile") or {}).get("exit_type") or "")
logger.info(
local = _patch_local_state(profile_abs, log)
log.info(
"chrome_session_restore_ensured profile_dir=%s prefs=%s existed=%s "
"restore_on_startup %s->%s exit_type %s->%s",
"restore_on_startup %s->%s exit_type %s->%s local_state=%s",
profile_abs,
prefs,
existed,
@@ -68,6 +114,7 @@ def ensure_session_restore(profile_dir: str) -> Dict[str, Any]:
after,
exit_before or "-",
exit_after or "-",
local,
)
return {
"ok": True,
@@ -77,4 +124,5 @@ def ensure_session_restore(profile_dir: str) -> Dict[str, Any]:
"restore_after": after,
"exit_type_before": exit_before,
"exit_type_after": exit_after,
"local_state": local,
}