KiroProxy User
chore: repo cleanup and maintenance
0edbd7b
"""浏览器检测和打开"""
import os
import shlex
import shutil
import subprocess
import platform
from dataclasses import dataclass
from typing import List, Optional
@dataclass
class BrowserInfo:
id: str
name: str
path: str
supports_incognito: bool
incognito_arg: str = ""
# 浏览器配置
BROWSER_CONFIGS = {
"chrome": {
"names": ["google-chrome", "google-chrome-stable", "chrome", "chromium", "chromium-browser"],
"display": "Chrome",
"incognito": "--incognito",
},
"firefox": {
"names": ["firefox", "firefox-esr"],
"display": "Firefox",
"incognito": "--private-window",
},
"edge": {
"names": ["microsoft-edge", "microsoft-edge-stable", "msedge"],
"display": "Edge",
"incognito": "--inprivate",
},
"brave": {
"names": ["brave", "brave-browser"],
"display": "Brave",
"incognito": "--incognito",
},
"opera": {
"names": ["opera"],
"display": "Opera",
"incognito": "--private",
},
"vivaldi": {
"names": ["vivaldi", "vivaldi-stable"],
"display": "Vivaldi",
"incognito": "--incognito",
},
}
def detect_browsers() -> List[BrowserInfo]:
"""检测系统安装的浏览器"""
browsers = []
system = platform.system().lower()
if system == "windows":
import winreg
def normalize_exe_path(raw: str) -> Optional[str]:
if not raw:
return None
expanded = os.path.expandvars(raw.strip())
try:
parts = shlex.split(expanded, posix=False)
except ValueError:
parts = [expanded]
candidate = (parts[0] if parts else expanded).strip().strip('"')
if os.path.exists(candidate):
return candidate
lower = expanded.lower()
exe_idx = lower.find(".exe")
if exe_idx != -1:
candidate = expanded[:exe_idx + 4].strip().strip('"')
if os.path.exists(candidate):
return candidate
return None
def get_reg_path(exe_name: str) -> Optional[str]:
name = f"{exe_name}.exe"
for root in (winreg.HKEY_LOCAL_MACHINE, winreg.HKEY_CURRENT_USER):
try:
with winreg.OpenKey(root, rf"SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths\{name}") as key:
value, _ = winreg.QueryValueEx(key, "")
path = normalize_exe_path(value)
if path:
return path
except (FileNotFoundError, OSError, WindowsError):
pass
return None
for browser_id, config in BROWSER_CONFIGS.items():
path = None
for exe_name in config["names"]:
path = get_reg_path(exe_name)
if path:
break
if not path:
for exe_name in config["names"]:
path = shutil.which(exe_name)
if path:
break
if path:
browsers.append(BrowserInfo(
id=browser_id,
name=config["display"],
path=path,
supports_incognito=bool(config.get("incognito")),
incognito_arg=config.get("incognito", ""),
))
else:
for browser_id, config in BROWSER_CONFIGS.items():
for name in config["names"]:
path = shutil.which(name)
if path:
browsers.append(BrowserInfo(
id=browser_id,
name=config["display"],
path=path,
supports_incognito=bool(config.get("incognito")),
incognito_arg=config.get("incognito", ""),
))
break
# 添加默认浏览器选项
if browsers:
browsers.insert(0, BrowserInfo(
id="default",
name="默认浏览器",
path="xdg-open" if system == "linux" else "open",
supports_incognito=False,
incognito_arg="",
))
return browsers
def open_url(url: str, browser_id: str = "default", incognito: bool = False) -> bool:
"""用指定浏览器打开 URL"""
browsers = detect_browsers()
browser = next((b for b in browsers if b.id == browser_id), None)
if not browser:
# 降级到默认
browser = browsers[0] if browsers else None
if not browser:
return False
try:
if browser.id == "default":
# 使用系统默认浏览器
system = platform.system().lower()
if system == "linux":
subprocess.Popen(["xdg-open", url], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
elif system == "darwin":
subprocess.Popen(["open", url], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
else:
os.startfile(url)
else:
# 使用指定浏览器
args = [browser.path]
if incognito and browser.supports_incognito and browser.incognito_arg:
args.append(browser.incognito_arg)
args.append(url)
subprocess.Popen(args, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
return True
except Exception as e:
print(f"[Browser] 打开失败: {e}")
return False
def get_browsers_info() -> List[dict]:
"""获取浏览器信息列表"""
return [
{
"id": b.id,
"name": b.name,
"supports_incognito": b.supports_incognito,
}
for b in detect_browsers()
]