Source file src/cmd/internal/browser/browser.go

     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  	exec "internal/execabs"
    10  	"os"
    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  }
    68  

View as plain text