From b3bcb541b6acf27ac2e6804ad15f762433b762bf Mon Sep 17 00:00:00 2001 From: Xavier Lange Date: Sat, 6 Jun 2026 14:46:46 -0400 Subject: [PATCH 1/2] fix(browser): resolve profiles when browser is configured by path resolveBrowserProfileArgs and GetProfilesForBrowser looked up the browser in browsers.json by bundle ID or app name only. A handler that specifies the browser by path (appType "path", e.g. name "/Applications/Firefox.app") passes that path as the identifier, which matches neither, so no profile argument was emitted and the browser opened without the requested profile. For Firefox this had a worse symptom: with no profile argument the launch fell into Firefox's default profile selection, which on recent versions shows the new profile-selector ("ShowSelector") window. Passing -P/-profile avoids that path entirely. Add findBrowserInfo, which also matches an ".app" bundle path by its basename (minus ".app") against the app name, and use it in both call sites. Profile detection now works for path-based configs for Firefox and Chromium alike. Co-Authored-By: Claude Opus 4.8 --- apps/finicky/src/browser/launcher.go | 38 ++++++++++--------- apps/finicky/src/browser/launcher_test.go | 46 +++++++++++++++++++++++ 2 files changed, 67 insertions(+), 17 deletions(-) create mode 100644 apps/finicky/src/browser/launcher_test.go diff --git a/apps/finicky/src/browser/launcher.go b/apps/finicky/src/browser/launcher.go index a3a71200..c802090d 100644 --- a/apps/finicky/src/browser/launcher.go +++ b/apps/finicky/src/browser/launcher.go @@ -147,6 +147,25 @@ func LaunchBrowser(config BrowserConfig, dryRun bool, openInBackgroundByDefault return nil } +// findBrowserInfo locates a browser in browsers.json by bundle ID, app name, or +// an app bundle path (e.g. "/Applications/Firefox.app"). For a path, the +// basename without the ".app" suffix is matched against the app name, so profile +// detection works for configs that specify the browser by path (appType +// "path"), not just by bundle ID or app name. +func findBrowserInfo(browsersJson []browserInfo, identifier string) *browserInfo { + base := identifier + if strings.HasSuffix(base, ".app") { + base = strings.TrimSuffix(filepath.Base(base), ".app") + } + for i := range browsersJson { + b := &browsersJson[i] + if b.ID == identifier || b.AppName == identifier || (base != "" && b.AppName == base) { + return b + } + } + return nil +} + func resolveBrowserProfileArgs(identifier string, profile string) ([]string, bool) { var browsersJson []browserInfo if err := json.Unmarshal(browsersJsonData, &browsersJson); err != nil { @@ -154,15 +173,7 @@ func resolveBrowserProfileArgs(identifier string, profile string) ([]string, boo return nil, false } - // Try to find matching browser by bundle ID - var matchedBrowser *browserInfo - for _, browser := range browsersJson { - if browser.ID == identifier || browser.AppName == identifier { - matchedBrowser = &browser - break - } - } - + matchedBrowser := findBrowserInfo(browsersJson, identifier) if matchedBrowser == nil { return nil, false } @@ -347,14 +358,7 @@ func GetProfilesForBrowser(identifier string) []string { return []string{} } - var matchedBrowser *browserInfo - for i := range browsersJson { - if browsersJson[i].ID == identifier || browsersJson[i].AppName == identifier { - matchedBrowser = &browsersJson[i] - break - } - } - + matchedBrowser := findBrowserInfo(browsersJson, identifier) if matchedBrowser == nil { return []string{} } diff --git a/apps/finicky/src/browser/launcher_test.go b/apps/finicky/src/browser/launcher_test.go new file mode 100644 index 00000000..03840aa2 --- /dev/null +++ b/apps/finicky/src/browser/launcher_test.go @@ -0,0 +1,46 @@ +package browser + +import "testing" + +func TestFindBrowserInfo(t *testing.T) { + browsers := []browserInfo{ + {ConfigDirRelative: "Firefox", ID: "org.mozilla.firefox", AppName: "Firefox", Type: "Firefox"}, + {ConfigDirRelative: "Firefox", ID: "org.mozilla.firefoxdeveloperedition", AppName: "Firefox Developer Edition", Type: "Firefox"}, + {ConfigDirRelative: "zen", ID: "app.zen-browser.zen", AppName: "Zen", Type: "Firefox"}, + {ConfigDirRelative: "Google/Chrome", ID: "com.google.Chrome", AppName: "Google Chrome", Type: "Chromium"}, + } + + cases := []struct { + name string + identifier string + wantID string // "" means expect no match + }{ + {"by app name", "Firefox", "org.mozilla.firefox"}, + {"by bundle id", "org.mozilla.firefox", "org.mozilla.firefox"}, + {"by .app path", "/Applications/Firefox.app", "org.mozilla.firefox"}, + {"by .app path with spaces", "/Applications/Firefox Developer Edition.app", "org.mozilla.firefoxdeveloperedition"}, + {"zen by path", "/Applications/Zen.app", "app.zen-browser.zen"}, + {"chromium by path", "/Applications/Google Chrome.app", "com.google.Chrome"}, + {"unknown app name", "Safari", ""}, + {"unknown path", "/Applications/Safari.app", ""}, + {"path basename must not partial-match", "/Applications/Firefoxxx.app", ""}, + } + + for _, c := range cases { + t.Run(c.name, func(t *testing.T) { + got := findBrowserInfo(browsers, c.identifier) + if c.wantID == "" { + if got != nil { + t.Fatalf("expected no match for %q, got %q", c.identifier, got.ID) + } + return + } + if got == nil { + t.Fatalf("expected match %q for %q, got nil", c.wantID, c.identifier) + } + if got.ID != c.wantID { + t.Fatalf("for %q: got %q, want %q", c.identifier, got.ID, c.wantID) + } + }) + } +} From fc6683bed75127ddf9ac2b13e8ed1a5157133443 Mon Sep 17 00:00:00 2001 From: Xavier Lange Date: Sat, 6 Jun 2026 14:46:46 -0400 Subject: [PATCH 2/2] fix(build): remove stale bundle before mv in local build The local build path ran `mv Finicky-arm64.app Finicky.app` without first removing an existing build/Finicky.app. If one was left from a previous build, mv nested the new bundle inside the old directory and, under `set -e`, the script aborted before copying to /Applications -- silently leaving the previously installed app in place. Remove the destination bundle before the mv. Co-Authored-By: Claude Opus 4.8 --- scripts/build.sh | 3 +++ 1 file changed, 3 insertions(+) diff --git a/scripts/build.sh b/scripts/build.sh index cc67f335..ff2f6866 100755 --- a/scripts/build.sh +++ b/scripts/build.sh @@ -89,6 +89,9 @@ else APP_NAME="Finicky.app" # Rename arch build to plain Finicky.app build_arch arm64 + # Remove any stale bundle first; otherwise mv nests the new build inside it + # and (with set -e) aborts before installing, silently leaving the old app. + rm -rf apps/finicky/build/${APP_NAME} mv apps/finicky/build/Finicky-arm64.app apps/finicky/build/${APP_NAME} copy_assets ${APP_NAME}