diff --git a/browser/zen/zen.go b/browser/zen/zen.go new file mode 100644 index 0000000..375ab5e --- /dev/null +++ b/browser/zen/zen.go @@ -0,0 +1,22 @@ +// Zen (https://zen-browser.app) is a Firefox fork that keeps its own +// profile tree, separate from Firefox's, but reuses Firefox's cookies.sqlite +// and sessionstore formats verbatim. +package zen + +import ( + "github.com/browserutils/kooky" + "github.com/browserutils/kooky/internal/firefox" + "github.com/browserutils/kooky/internal/firefox/find" +) + +type zenFinder struct{} + +var _ kooky.CookieStoreFinder = (*zenFinder)(nil) + +func init() { + kooky.RegisterFinder(`zen`, &zenFinder{}) +} + +func (f *zenFinder) FindCookieStores() kooky.CookieStoreSeq { + return firefox.CookieStoresForProfiles(find.FindZenProfiles()) +} diff --git a/internal/firefox/find/find.go b/internal/firefox/find/find.go index b5adb58..1f10530 100644 --- a/internal/firefox/find/find.go +++ b/internal/firefox/find/find.go @@ -22,6 +22,14 @@ func FindFirefoxProfiles() iter.Seq2[Profile, error] { return FindProfiles(firefoxRoots, `firefox`) } +// FindZenProfiles returns all Zen Browser (https://zen-browser.app) profiles +// from known root directories. Zen is a Firefox fork that keeps its own +// profile tree — separate from Firefox's — but writes profiles.ini in the +// same format, so it reuses FindProfiles/FindProfilesInRoot as-is. +func FindZenProfiles() iter.Seq2[Profile, error] { + return FindProfiles(zenRoots, `zen`) +} + // FindProfilesInRoot parses a single profiles.ini from rootDir // and returns the discovered profiles. func FindProfilesInRoot(rootDir, browserName string) ([]Profile, error) { diff --git a/internal/firefox/find/zen_darwin.go b/internal/firefox/find/zen_darwin.go new file mode 100644 index 0000000..d990896 --- /dev/null +++ b/internal/firefox/find/zen_darwin.go @@ -0,0 +1,20 @@ +//go:build darwin && !ios + +package find + +import ( + "os" + "path/filepath" +) + +func zenRoots(yield func(string, error) bool) { + // "$HOME/Library/Application Support/zen" + cfgDir, err := os.UserConfigDir() + if err != nil { + _ = yield(``, err) + return + } + if !yield(filepath.Join(cfgDir, `zen`), nil) { + return + } +} diff --git a/internal/firefox/find/zen_other.go b/internal/firefox/find/zen_other.go new file mode 100644 index 0000000..1250675 --- /dev/null +++ b/internal/firefox/find/zen_other.go @@ -0,0 +1,5 @@ +//go:build !windows && !linux + +package find + +func windowsZenRoots(yield func(string, error) bool) {} diff --git a/internal/firefox/find/zen_others.go b/internal/firefox/find/zen_others.go new file mode 100644 index 0000000..61bcc16 --- /dev/null +++ b/internal/firefox/find/zen_others.go @@ -0,0 +1,7 @@ +//go:build plan9 || android || ios || js || aix + +package find + +import "errors" + +func zenRoots(yield func(string, error) bool) { yield(``, errors.New(`not implemented`)) } diff --git a/internal/firefox/find/zen_unix.go b/internal/firefox/find/zen_unix.go new file mode 100644 index 0000000..9353cc3 --- /dev/null +++ b/internal/firefox/find/zen_unix.go @@ -0,0 +1,45 @@ +//go:build !windows && !darwin && !plan9 && !android && !js && !aix + +package find + +import ( + "os" + "path/filepath" + + "github.com/browserutils/kooky/internal/windowsx" +) + +func zenRoots(yield func(string, error) bool) { + home, err := os.UserHomeDir() + if err != nil { + _ = yield(``, err) + return + } + // tarball / AUR install, current default: + // https://docs.zen-browser.app/guides/install-linux + if !yield(filepath.Join(home, `.zen`), nil) { + return + } + // Flatpak (same doc) + if !yield(filepath.Join(home, `.var`, `app`, `app.zen_browser.zen`, `.zen`), nil) { + return + } + // Newer XDG Base Directory-following builds + // (zen-browser/desktop#12366) — gated behind the Twilight channel as of + // this writing, kept here so this doesn't need a follow-up once it + // reaches the stable channel. + if cfgDir, err := os.UserConfigDir(); err == nil { + if !yield(filepath.Join(cfgDir, `zen`), nil) { + return + } + } + // on WSL Linux add Windows paths + if !windowsx.IsWSL() { + return + } + for r, err := range windowsZenRoots { + if !yield(r, err) { + return + } + } +} diff --git a/internal/firefox/find/zen_w.go b/internal/firefox/find/zen_w.go new file mode 100644 index 0000000..6b11273 --- /dev/null +++ b/internal/firefox/find/zen_w.go @@ -0,0 +1,21 @@ +//go:build windows || linux + +package find + +import ( + "path/filepath" + + "github.com/browserutils/kooky/internal/windowsx" +) + +// for Windows and WSL + +func windowsZenRoots(yield func(string, error) bool) { + // "%AppData%\zen" — https://docs.zen-browser.app/faq + appData, err := windowsx.AppData() + if err != nil { + _ = yield(``, err) + return + } + _ = yield(filepath.Join(appData, `zen`), nil) +} diff --git a/internal/firefox/find/zen_windows.go b/internal/firefox/find/zen_windows.go new file mode 100644 index 0000000..f821adc --- /dev/null +++ b/internal/firefox/find/zen_windows.go @@ -0,0 +1,5 @@ +//go:build windows + +package find + +var zenRoots = windowsZenRoots