ffctl/lib/marionette/gecko.go

87 lines
1.5 KiB
Go
Raw Normal View History

2024-02-09 08:59:56 +00:00
package marionette
2024-02-09 01:53:56 +00:00
import (
"context"
"errors"
2024-02-09 08:59:56 +00:00
"io"
2024-02-09 01:53:56 +00:00
"net"
"os"
"os/exec"
)
2024-02-09 08:59:56 +00:00
func haveProg(prog string) bool {
_, err := exec.LookPath(prog)
2024-02-09 01:53:56 +00:00
return err == nil
}
2024-02-09 08:59:56 +00:00
func WithGecko(ctx context.Context, fn func(context.Context, *TCPTransport) error) (_retErr error) {
2024-02-09 01:53:56 +00:00
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 {
2024-02-09 08:59:56 +00:00
case haveProg("firefox"):
2024-02-09 01:53:56 +00:00
prog = "firefox"
2024-02-09 08:59:56 +00:00
case haveProg("iceweasel"):
2024-02-09 01:53:56 +00:00
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()) }()
2024-02-09 08:59:56 +00:00
trans, err := NewTransport(conn)
if err != nil {
return err
}
if _, err := trans.CmdNewSession(nil); err != nil {
return err
}
defer func() {
_, err := trans.CmdQuit()
maybeSetErr(err)
maybeSetErr(conn.CloseWrite())
_, err = io.Copy(io.Discard, conn)
maybeSetErr(err)
}()
return fn(ctx, trans)
2024-02-09 01:53:56 +00:00
}