ffctl/ffscript/geckoinstance.go

69 lines
1.2 KiB
Go
Raw Normal View History

2024-02-09 01:53:56 +00:00
package main
import (
"context"
"errors"
"net"
"os"
"os/exec"
)
func haveCmd(cmd string) bool {
_, err := exec.LookPath(cmd)
return err == nil
}
func WithGecko(ctx context.Context, fn func(context.Context, *net.TCPConn) error) (_retErr error) {
maybeSetErr := func(_err error) {
if _retErr == nil && _err != nil {
_retErr = _err
}
}
profile, err := os.MkdirTemp("", "")
if err != nil {
return err
}
defer func() { maybeSetErr(os.RemoveAll(profile)) }()
var prog string
switch {
case haveCmd("firefox"):
prog = "firefox"
case haveCmd("iceweasel"):
prog = "iceweasel"
default:
return errors.New("no gecko browser found")
}
cmd := exec.CommandContext(ctx, prog,
"--new-instance",
"--profile", profile,
"--marionette")
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
if err := cmd.Start(); err != nil {
return err
}
defer func() { maybeSetErr(cmd.Wait()) }()
defer func() {
if _retErr != nil {
cmd.Process.Signal(os.Interrupt)
}
}()
var conn *net.TCPConn
for conn == nil {
select {
case <-ctx.Done():
return ctx.Err()
default:
_conn, _ := net.Dial("tcp", "localhost:2828")
conn, _ = _conn.(*net.TCPConn)
}
}
defer func() { maybeSetErr(conn.Close()) }()
return fn(ctx, conn)
}