diff --git a/apps/m9zCtrlTty/firefox_install.go b/apps/m9zCtrlTty/firefox_install.go index 01c16dc..22de4f6 100644 --- a/apps/m9zCtrlTty/firefox_install.go +++ b/apps/m9zCtrlTty/firefox_install.go @@ -55,11 +55,29 @@ func isFirefoxUsable() bool { } func isFirefoxInstalled() bool { - cmd := exec.Command("which", "firefox") - out, err := cmd.CombinedOutput() - ok := err == nil - kioskDebugf("firefox install path check ok=%v output=%q err=%v", ok, strings.TrimSpace(string(out)), err) - return ok + if path, err := exec.LookPath("firefox"); err == nil { + kioskDebugf("firefox install path check ok=true path=%s source=PATH", path) + return true + } + + for _, path := range []string{ + "/usr/bin/firefox", + "/usr/local/bin/firefox", + "/snap/bin/firefox", + } { + if isExecutableFile(path) { + kioskDebugf("firefox install path check ok=true path=%s source=fallback", path) + return true + } + } + + kioskDebugf("firefox install path check ok=false") + return false +} + +func isExecutableFile(path string) bool { + info, err := os.Stat(path) + return err == nil && !info.IsDir() && info.Mode()&0111 != 0 } func installFirefox() error { diff --git a/apps/m9zCtrlTty/install.go b/apps/m9zCtrlTty/install.go index c995d76..3641bf6 100644 --- a/apps/m9zCtrlTty/install.go +++ b/apps/m9zCtrlTty/install.go @@ -7,20 +7,33 @@ import ( ) func install() error { - kioskInfof("checking firefox usability") + kioskInfof("checking firefox installation") var firefoxInstallErr error - if isFirefoxUsable() { - kioskInfof("firefox is usable") + + firefoxInstalled := isFirefoxInstalled() + firefoxUsable := false + if firefoxInstalled { + firefoxUsable = isFirefoxUsable() + } + markerExists := hasFirefoxInstallMarker() + kioskInfof("firefox startup state installed=%v usable=%v markerExists=%v", firefoxInstalled, firefoxUsable, markerExists) + + switch { + case firefoxInstalled && firefoxUsable: + kioskInfof("firefox installed and usable") fmt.Println("Firefox is installed and usable") if err := writeFirefoxInstallMarker("usable"); err != nil { kioskWarnf("write firefox install marker failed err=%v", err) } - } else if hasFirefoxInstallMarker() { - kioskWarnf("firefox unusable but install marker exists; skip automatic repair") - fmt.Println("Firefox unusable; skip automatic repair on startup") - } else { - kioskWarnf("firefox unusable and no install marker; starting first-time install") - fmt.Println("Firefox missing or unusable, installing...") + case firefoxInstalled: + kioskWarnf("firefox is installed but version check failed; skip automatic reinstall") + fmt.Println("Firefox installed but unusable; skip automatic reinstall on startup") + case markerExists: + kioskWarnf("firefox executable missing but install marker exists; skip automatic reinstall") + fmt.Println("Firefox missing; skip automatic reinstall on startup") + case shouldAutoInstallFirefox(firefoxInstalled, markerExists): + kioskWarnf("firefox executable missing and no install marker; starting first-time install") + fmt.Println("Firefox missing, installing...") if err := installFirefox(); err != nil { kioskErrorf("firefox first-time install failed err=%v", err) fmt.Printf("install Firefox failed: %v\n", err) @@ -59,3 +72,7 @@ func install() error { } return nil } + +func shouldAutoInstallFirefox(installed bool, markerExists bool) bool { + return !installed && !markerExists +} diff --git a/apps/m9zCtrlTty/install_test.go b/apps/m9zCtrlTty/install_test.go new file mode 100644 index 0000000..517e74c --- /dev/null +++ b/apps/m9zCtrlTty/install_test.go @@ -0,0 +1,39 @@ +package main + +import "testing" + +func TestShouldAutoInstallFirefox(t *testing.T) { + tests := []struct { + name string + installed bool + markerExists bool + want bool + }{ + { + name: "missing without marker can install", + installed: false, + markerExists: false, + want: true, + }, + { + name: "installed must not reinstall even when unusable", + installed: true, + markerExists: false, + want: false, + }, + { + name: "missing with marker must not reinstall", + installed: false, + markerExists: true, + want: false, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if got := shouldAutoInstallFirefox(tt.installed, tt.markerExists); got != tt.want { + t.Fatalf("shouldAutoInstallFirefox(%v, %v) = %v, want %v", tt.installed, tt.markerExists, got, tt.want) + } + }) + } +}