// Copyright 2016 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // Package browser provides utilities for interacting with users' browsers. package browser import ( "os" "os/exec" "runtime" "time" ) // Commands returns a list of possible commands to use to open a url. func Commands() [][]string { var cmds [][]string if exe := os.Getenv("BROWSER"); exe != "" { cmds = append(cmds, []string{exe}) } switch runtime.GOOS { case "darwin": cmds = append(cmds, []string{"/usr/bin/open"}) case "windows": cmds = append(cmds, []string{"cmd", "/c", "start"}) default: if os.Getenv("DISPLAY") != "" { // xdg-open is only for use in a desktop environment. cmds = append(cmds, []string{"xdg-open"}) } } cmds = append(cmds, []string{"chrome"}, []string{"google-chrome"}, []string{"chromium"}, []string{"firefox"}, ) return cmds } // Open tries to open url in a browser and reports whether it succeeded. func Open(url string) bool { for _, args := range Commands() { cmd := exec.Command(args[0], append(args[1:], url)...) if cmd.Start() == nil && appearsSuccessful(cmd, 3*time.Second) { return true } } return false } // appearsSuccessful reports whether the command appears to have run successfully. // If the command runs longer than the timeout, it's deemed successful. // If the command runs within the timeout, it's deemed successful if it exited cleanly. func appearsSuccessful(cmd *exec.Cmd, timeout time.Duration) bool { errc := make(chan error, 1) go func() { errc <- cmd.Wait() }() select { case <-time.After(timeout): return true case err := <-errc: return err == nil } }