-
1
-
2
-
3
-
4
-
5
-
6
-
7
-
8
-
9
-
10
-
11
-
12
-
13
-
14
-
15
-
16
-
17
-
18
-
19
-
20
-
21
-
22
-
23
-
24
-
25
-
26
-
27
-
28
-
29
-
30
-
31
-
32
-
33
-
34
-
35
-
36
-
37
-
38
-
39
-
40
-
41
-
42
-
43
-
44
-
45
-
46
-
47
-
48
-
49
-
50
-
51
-
52
-
53
-
54
-
55
-
56
-
57
-
58
-
59
-
60
-
61
-
62
-
63
-
64
-
65
-
66
-
67
-
68
-
69
-
70
-
71
-
72
-
73
-
74
-
75
-
76
-
77
-
78
-
79
-
80
-
81
-
82
-
83
-
84
-
85
-
86
-
87
-
88
-
89
-
90
-
91
-
92
-
93
-
94
-
95
-
96
-
97
-
98
-
99
-
100
-
101
-
102
-
103
-
104
-
105
-
106
-
107
-
108
-
109
-
110
-
111
-
112
-
113
-
114
-
115
-
116
-
117
-
118
-
119
-
120
-
121
-
122
-
123
-
124
-
125
-
126
-
127
-
128
-
129
-
130
-
131
-
132
-
133
-
134
-
135
-
136
-
137
// Package webbrowser provides a simple API for opening web pages on your
// default browser.
package webbrowser
import (
"errors"
"fmt"
"net/url"
"os"
"os/exec"
"runtime"
"strings"
)
var (
ErrCantOpenBrowser = errors.New("webbrowser: can't open browser")
ErrNoCandidates = errors.New("webbrowser: no browser candidate found for your OS")
)
// Candidates contains a list of registered `Browser`s that will be tried with Open.
var Candidates []Browser
type Browser interface {
// Command returns a ready to be used Cmd that will open an URL.
Command(string) (*exec.Cmd, error)
// Open tries to open a URL in your default browser. NOTE: This may cause
// your program to hang until the browser process is closed in some OSes,
// see https://github.com/toqueteos/webbrowser/issues/4.
Open(string) error
}
// Open tries to open a URL in your default browser ensuring you have a display
// set up and not running this from SSH. NOTE: This may cause your program to
// hang until the browser process is closed in some OSes, see
// https://github.com/toqueteos/webbrowser/issues/4.
func Open(s string) (err error) {
if len(Candidates) == 0 {
return ErrNoCandidates
}
// Try to determine if there's a display available (only linux) and we
// aren't on a terminal (all but windows).
switch runtime.GOOS {
case "linux":
// No display, no need to open a browser. Lynx users **MAY** have
// something to say about this.
if os.Getenv("DISPLAY") == "" {
return fmt.Errorf("webbrowser: tried to open %q, no screen found", s)
}
fallthrough
case "darwin":
// Check SSH env vars.
if os.Getenv("SSH_CLIENT") != "" || os.Getenv("SSH_TTY") != "" {
return fmt.Errorf("webbrowser: tried to open %q, but you are running a shell session", s)
}
}
// Try all candidates
for _, candidate := range Candidates {
err := candidate.Open(s)
if err == nil {
return nil
}
}
return ErrCantOpenBrowser
}
func init() {
// Register the default Browser for current OS, if it exists.
if os, ok := osCommand[runtime.GOOS]; ok {
Candidates = append(Candidates, browserCommand{os.cmd, os.args})
}
}
var (
osCommand = map[string]*browserCommand{
"android": &browserCommand{"xdg-open", nil},
"darwin": &browserCommand{"open", nil},
"freebsd": &browserCommand{"xdg-open", nil},
"linux": &browserCommand{"xdg-open", nil},
"netbsd": &browserCommand{"xdg-open", nil},
"openbsd": &browserCommand{"xdg-open", nil}, // It may be open instead
"windows": &browserCommand{"cmd", []string{"/c", "start"}},
}
winSchemes = [3]string{"https", "http", "file"}
)
type browserCommand struct {
cmd string
args []string
}
func (b browserCommand) Command(s string) (*exec.Cmd, error) {
u, err := url.Parse(s)
if err != nil {
return nil, err
}
validUrl := ensureValidURL(u)
b.args = append(b.args, validUrl)
return exec.Command(b.cmd, b.args...), nil
}
func (b browserCommand) Open(s string) error {
cmd, err := b.Command(s)
if err != nil {
return err
}
return cmd.Run()
}
func ensureScheme(u *url.URL) {
for _, s := range winSchemes {
if u.Scheme == s {
return
}
}
u.Scheme = "http"
}
func ensureValidURL(u *url.URL) string {
// Enforce a scheme (windows requires scheme to be set to work properly).
ensureScheme(u)
s := u.String()
// Escape characters not allowed by cmd/bash
switch runtime.GOOS {
case "windows":
s = strings.Replace(s, "&", `^&`, -1)
}
return s
}