golang.org/x/tools/gopls@v0.15.3/internal/util/browser/browser.go (about) 1 // Copyright 2016 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 // Package browser provides utilities for interacting with users' browsers. 6 package browser 7 8 import ( 9 "os" 10 "os/exec" 11 "runtime" 12 "time" 13 ) 14 15 // Commands returns a list of possible commands to use to open a url. 16 func Commands() [][]string { 17 var cmds [][]string 18 if exe := os.Getenv("BROWSER"); exe != "" { 19 cmds = append(cmds, []string{exe}) 20 } 21 switch runtime.GOOS { 22 case "darwin": 23 cmds = append(cmds, []string{"/usr/bin/open"}) 24 case "windows": 25 cmds = append(cmds, []string{"cmd", "/c", "start"}) 26 default: 27 if os.Getenv("DISPLAY") != "" { 28 // xdg-open is only for use in a desktop environment. 29 cmds = append(cmds, []string{"xdg-open"}) 30 } 31 } 32 cmds = append(cmds, 33 []string{"chrome"}, 34 []string{"google-chrome"}, 35 []string{"chromium"}, 36 []string{"firefox"}, 37 ) 38 return cmds 39 } 40 41 // Open tries to open url in a browser and reports whether it succeeded. 42 func Open(url string) bool { 43 for _, args := range Commands() { 44 cmd := exec.Command(args[0], append(args[1:], url)...) 45 if cmd.Start() == nil && appearsSuccessful(cmd, 3*time.Second) { 46 return true 47 } 48 } 49 return false 50 } 51 52 // appearsSuccessful reports whether the command appears to have run successfully. 53 // If the command runs longer than the timeout, it's deemed successful. 54 // If the command runs within the timeout, it's deemed successful if it exited cleanly. 55 func appearsSuccessful(cmd *exec.Cmd, timeout time.Duration) bool { 56 errc := make(chan error, 1) 57 go func() { 58 errc <- cmd.Wait() 59 }() 60 61 select { 62 case <-time.After(timeout): 63 return true 64 case err := <-errc: 65 return err == nil 66 } 67 }