From ba1e2a20167cb97f1d9753b1f4f53b506ad549f3 Mon Sep 17 00:00:00 2001 From: Rodrigo Moran Date: Mon, 4 Aug 2025 13:57:18 -0400 Subject: [PATCH] add support for brave browser --- browser/all/import.go | 1 + browser/brave/brave.go | 30 ++++++++++++++++++ browser/brave/find.go | 43 ++++++++++++++++++++++++++ internal/chrome/find/find.go | 4 +++ internal/chrome/find/find_android.go | 2 ++ internal/chrome/find/find_darwin.go | 12 +++++++ internal/chrome/find/find_others.go | 2 ++ internal/chrome/find/find_otherunix.go | 4 +++ internal/chrome/find/find_unix.go | 36 +++++++++++++++++++++ internal/chrome/find/find_windows.go | 1 + internal/chrome/find/find_wsl.go | 12 +++++++ 11 files changed, 147 insertions(+) create mode 100644 browser/brave/brave.go create mode 100644 browser/brave/find.go diff --git a/browser/all/import.go b/browser/all/import.go index 7f0fdc9..bfd7a70 100644 --- a/browser/all/import.go +++ b/browser/all/import.go @@ -1,6 +1,7 @@ package all import ( + _ "github.com/browserutils/kooky/browser/brave" _ "github.com/browserutils/kooky/browser/browsh" _ "github.com/browserutils/kooky/browser/chrome" _ "github.com/browserutils/kooky/browser/chromium" diff --git a/browser/brave/brave.go b/browser/brave/brave.go new file mode 100644 index 0000000..2db07b6 --- /dev/null +++ b/browser/brave/brave.go @@ -0,0 +1,30 @@ +package brave + +import ( + "context" + + "github.com/browserutils/kooky" + "github.com/browserutils/kooky/internal/chrome" + "github.com/browserutils/kooky/internal/cookies" +) + +func ReadCookies(ctx context.Context, filename string, filters ...kooky.Filter) ([]*kooky.Cookie, error) { + return cookies.SingleRead(cookieStore, filename, filters...).ReadAllCookies(ctx) +} + +func TraverseCookies(filename string, filters ...kooky.Filter) kooky.CookieSeq { + return cookies.SingleRead(cookieStore, filename, filters...) +} + +// CookieStore has to be closed with CookieStore.Close() after use. +func CookieStore(filename string, filters ...kooky.Filter) (kooky.CookieStore, error) { + return cookieStore(filename, filters...) +} + +func cookieStore(filename string, filters ...kooky.Filter) (*cookies.CookieJar, error) { + s := &chrome.CookieStore{} + s.FileNameStr = filename + s.BrowserStr = `brave` + + return cookies.NewCookieJar(s, filters...), nil +} diff --git a/browser/brave/find.go b/browser/brave/find.go new file mode 100644 index 0000000..1961670 --- /dev/null +++ b/browser/brave/find.go @@ -0,0 +1,43 @@ +package brave + +import ( + "github.com/browserutils/kooky" + "github.com/browserutils/kooky/internal/chrome" + "github.com/browserutils/kooky/internal/chrome/find" + "github.com/browserutils/kooky/internal/cookies" +) + +type braveFinder struct{} + +var _ kooky.CookieStoreFinder = (*braveFinder)(nil) + +func init() { + kooky.RegisterFinder(`brave`, &braveFinder{}) +} + +func (f *braveFinder) FindCookieStores() kooky.CookieStoreSeq { + return func(yield func(kooky.CookieStore, error) bool) { + for file, err := range find.FindBraveCookieStoreFiles() { + if err != nil { + if !yield(nil, err) { + return + } + continue + } + st := &cookies.CookieJar{ + CookieStore: &chrome.CookieStore{ + DefaultCookieStore: cookies.DefaultCookieStore{ + BrowserStr: file.Browser, + ProfileStr: file.Profile, + OSStr: file.OS, + IsDefaultProfileBool: file.IsDefaultProfile, + FileNameStr: file.Path, + }, + }, + } + if !yield(st, nil) { + return + } + } + } +} diff --git a/internal/chrome/find/find.go b/internal/chrome/find/find.go index 5fd49bf..7c04b19 100644 --- a/internal/chrome/find/find.go +++ b/internal/chrome/find/find.go @@ -26,6 +26,10 @@ func FindChromiumCookieStoreFiles() iter.Seq2[*chromeCookieStoreFile, error] { return FindCookieStoreFiles(chromiumRoots, `chromium`) } +func FindBraveCookieStoreFiles() iter.Seq2[*chromeCookieStoreFile, error] { + return FindCookieStoreFiles(braveRoots, `brave`) +} + func FindCookieStoreFiles(rootsFunc iter.Seq2[string, error], browserName string) iter.Seq2[*chromeCookieStoreFile, error] { return func(yield func(*chromeCookieStoreFile, error) bool) { if rootsFunc == nil { diff --git a/internal/chrome/find/find_android.go b/internal/chrome/find/find_android.go index e9b64bb..fb7ed79 100644 --- a/internal/chrome/find/find_android.go +++ b/internal/chrome/find/find_android.go @@ -15,3 +15,5 @@ func chromeRoots(yield func(string, error) bool) { } func chromiumRoots(yield func(string, error) bool) { _ = yield(``, errNotImplemented) } + +func braveRoots(yield func(string, error) bool) { _ = yield(``, errNotImplemented) } diff --git a/internal/chrome/find/find_darwin.go b/internal/chrome/find/find_darwin.go index 4525465..13ecb1f 100644 --- a/internal/chrome/find/find_darwin.go +++ b/internal/chrome/find/find_darwin.go @@ -35,3 +35,15 @@ func chromiumRoots(yield func(string, error) bool) { return } } + +func braveRoots(yield func(string, error) bool) { + // "$HOME/Library/Application Support" + cfgDir, err := os.UserConfigDir() + if err != nil { + _ = yield(``, err) + return + } + if !yield(filepath.Join(cfgDir, `BraveSoftware`, `Brave-Browser`), nil) { + return + } +} diff --git a/internal/chrome/find/find_others.go b/internal/chrome/find/find_others.go index e4ad8c6..4cb34b4 100644 --- a/internal/chrome/find/find_others.go +++ b/internal/chrome/find/find_others.go @@ -9,3 +9,5 @@ var errNotImplemented = errors.New(`not implemented`) func chromeRoots(yield func(string, error) bool) { _ = yield(``, errNotImplemented) } func chromiumRoots(yield func(string, error) bool) { _ = yield(``, errNotImplemented) } + +func braveRoots(yield func(string, error) bool) { _ = yield(``, errNotImplemented) } diff --git a/internal/chrome/find/find_otherunix.go b/internal/chrome/find/find_otherunix.go index b88995a..6998532 100644 --- a/internal/chrome/find/find_otherunix.go +++ b/internal/chrome/find/find_otherunix.go @@ -9,3 +9,7 @@ func windowsChromeRoots(_ string) func(yield func(string, error) bool) { func windowsChromiumRoots(_ string) func(yield func(string, error) bool) { return func(yield func(string, error) bool) {} } + +func windowsBraveRoots(_ string) func(yield func(string, error) bool) { + return func(yield func(string, error) bool) {} +} diff --git a/internal/chrome/find/find_unix.go b/internal/chrome/find/find_unix.go index ff0a6c4..bae9f86 100644 --- a/internal/chrome/find/find_unix.go +++ b/internal/chrome/find/find_unix.go @@ -89,3 +89,39 @@ func chromiumRoots(yield func(string, error) bool) { } } } + +func braveRoots(yield func(string, error) bool) { + // "${XDG_CONFIG_HOME:-$HOME/.config}" + var dotConfigs []string + // fallback + if home, err := os.UserHomeDir(); err != nil { + if !yield(``, err) { + return + } + } else { + dotConfigs = append(dotConfigs, filepath.Join(home, `.config`)) + } + if dir, ok := os.LookupEnv(`XDG_CONFIG_HOME`); ok { + dotConfigs = append(dotConfigs, dir) + } + for _, dotConfig := range dotConfigs { + for _, p := range []string{ + filepath.Join(dotConfig, `BraveSoftware`, `Brave-Browser`), + filepath.Join(dotConfig, `brave-browser`), + } { + if !yield(p, nil) { + return + } + } + } + // on WSL Linux add Windows paths + appDataRoot, err := wsl.WSLAppDataRoot() + if err != nil && (errors.Is(err, wsl.ErrNotWSL) || !yield(``, err)) { + return + } + for r, err := range windowsBraveRoots(filepath.Join(appDataRoot, `Local`)) { + if !yield(r, err) { + return + } + } +} diff --git a/internal/chrome/find/find_windows.go b/internal/chrome/find/find_windows.go index ac6f18e..1b3d80c 100644 --- a/internal/chrome/find/find_windows.go +++ b/internal/chrome/find/find_windows.go @@ -10,4 +10,5 @@ import ( var ( chromeRoots = windowsChromeRoots(os.Getenv(`LocalAppData`)) chromiumRoots = windowsChromiumRoots(os.Getenv(`LocalAppData`)) + braveRoots = windowsBraveRoots(os.Getenv(`LocalAppData`)) ) diff --git a/internal/chrome/find/find_wsl.go b/internal/chrome/find/find_wsl.go index 505447c..8e2a3bd 100644 --- a/internal/chrome/find/find_wsl.go +++ b/internal/chrome/find/find_wsl.go @@ -38,3 +38,15 @@ func windowsChromiumRoots(dir string) func(yield func(string, error) bool) { } } } + +func windowsBraveRoots(dir string) func(yield func(string, error) bool) { + return func(yield func(string, error) bool) { + if len(dir) == 0 { + _ = yield(``, errors.New(`%LocalAppData% is empty`)) + return + } + if !yield(filepath.Join(dir, `BraveSoftware`, `Brave-Browser`, `User Data`), nil) { + return + } + } +}