mirror of
https://github.com/black-ant/Ant-Browser.git
synced 2026-07-14 18:48:55 +08:00
163 lines
3.9 KiB
Go
163 lines
3.9 KiB
Go
package backend
|
|
|
|
import (
|
|
"ant-chrome/backend/internal/snapshot"
|
|
"encoding/json"
|
|
"fmt"
|
|
"os"
|
|
"path/filepath"
|
|
"sort"
|
|
"strings"
|
|
"time"
|
|
|
|
"github.com/google/uuid"
|
|
)
|
|
|
|
// getProfileForSnapshot 获取实例信息(加锁)
|
|
func (a *App) getProfileForSnapshot(profileId string) (*BrowserProfile, error) {
|
|
a.browserMgr.Mutex.Lock()
|
|
defer a.browserMgr.Mutex.Unlock()
|
|
profile, exists := a.browserMgr.Profiles[profileId]
|
|
if !exists {
|
|
return nil, fmt.Errorf("实例不存在: %s", profileId)
|
|
}
|
|
return profile, nil
|
|
}
|
|
|
|
// BrowserSnapshotCreate 创建快照
|
|
func (a *App) BrowserSnapshotCreate(profileId, name string) (SnapshotInfo, error) {
|
|
profile, err := a.getProfileForSnapshot(profileId)
|
|
if err != nil {
|
|
return SnapshotInfo{}, err
|
|
}
|
|
if profile.Running {
|
|
return SnapshotInfo{}, fmt.Errorf("请先停止实例再创建快照")
|
|
}
|
|
|
|
userDataDir := a.browserMgr.ResolveUserDataDir(profile)
|
|
if _, err := os.Stat(userDataDir); os.IsNotExist(err) {
|
|
return SnapshotInfo{}, fmt.Errorf("用户数据目录不存在,无法创建快照")
|
|
}
|
|
|
|
snapDir, err := a.snapshotDir(profileId)
|
|
if err != nil {
|
|
return SnapshotInfo{}, err
|
|
}
|
|
|
|
snapshotID := uuid.NewString()
|
|
safeName := strings.ReplaceAll(name, string(os.PathSeparator), "_")
|
|
zipPath := filepath.Join(snapDir, snapshotID+"_"+safeName+".zip")
|
|
metaPath := filepath.Join(snapDir, snapshotID+"_"+safeName+".meta.json")
|
|
|
|
if err := snapshot.ZipDir(userDataDir, zipPath); err != nil {
|
|
return SnapshotInfo{}, fmt.Errorf("压缩失败: %w", err)
|
|
}
|
|
|
|
fi, err := os.Stat(zipPath)
|
|
if err != nil {
|
|
return SnapshotInfo{}, err
|
|
}
|
|
sizeMB := float64(fi.Size()) / 1024 / 1024
|
|
|
|
info := SnapshotInfo{
|
|
SnapshotId: snapshotID,
|
|
ProfileId: profileId,
|
|
Name: name,
|
|
SizeMB: sizeMB,
|
|
CreatedAt: time.Now().Format(time.RFC3339),
|
|
FilePath: zipPath,
|
|
}
|
|
|
|
metaData, _ := json.Marshal(info)
|
|
if err := os.WriteFile(metaPath, metaData, 0o644); err != nil {
|
|
return SnapshotInfo{}, err
|
|
}
|
|
|
|
info.FilePath = ""
|
|
return info, nil
|
|
}
|
|
|
|
// BrowserSnapshotList 列出实例的所有快照
|
|
func (a *App) BrowserSnapshotList(profileId string) ([]SnapshotInfo, error) {
|
|
snapDir, err := a.snapshotDir(profileId)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
entries, err := os.ReadDir(snapDir)
|
|
if err != nil {
|
|
if os.IsNotExist(err) {
|
|
return []SnapshotInfo{}, nil
|
|
}
|
|
return nil, err
|
|
}
|
|
|
|
var list []SnapshotInfo
|
|
for _, entry := range entries {
|
|
if entry.IsDir() || !strings.HasSuffix(entry.Name(), ".meta.json") {
|
|
continue
|
|
}
|
|
data, err := os.ReadFile(filepath.Join(snapDir, entry.Name()))
|
|
if err != nil {
|
|
continue
|
|
}
|
|
var info SnapshotInfo
|
|
if err := json.Unmarshal(data, &info); err != nil {
|
|
continue
|
|
}
|
|
info.FilePath = ""
|
|
list = append(list, info)
|
|
}
|
|
|
|
sort.Slice(list, func(i, j int) bool {
|
|
return list[i].CreatedAt > list[j].CreatedAt
|
|
})
|
|
return list, nil
|
|
}
|
|
|
|
// BrowserSnapshotRestore 恢复快照
|
|
func (a *App) BrowserSnapshotRestore(profileId, snapshotId string) error {
|
|
profile, err := a.getProfileForSnapshot(profileId)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if profile.Running {
|
|
return fmt.Errorf("请先停止实例再恢复快照")
|
|
}
|
|
|
|
snapDir, err := a.snapshotDir(profileId)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
metaPath, zipPath, err := snapshot.FindFiles(snapDir, snapshotId)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
_ = metaPath
|
|
|
|
userDataDir := a.browserMgr.ResolveUserDataDir(profile)
|
|
if err := os.RemoveAll(userDataDir); err != nil {
|
|
return fmt.Errorf("清空用户数据目录失败: %w", err)
|
|
}
|
|
if err := os.MkdirAll(userDataDir, 0o755); err != nil {
|
|
return err
|
|
}
|
|
return snapshot.UnzipTo(zipPath, userDataDir)
|
|
}
|
|
|
|
// BrowserSnapshotDelete 删除快照
|
|
func (a *App) BrowserSnapshotDelete(profileId, snapshotId string) error {
|
|
snapDir, err := a.snapshotDir(profileId)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
metaPath, zipPath, err := snapshot.FindFiles(snapDir, snapshotId)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
_ = os.Remove(zipPath)
|
|
_ = os.Remove(metaPath)
|
|
return nil
|
|
}
|