From 4029ec9df72b2e059eff09d92fec8e9fba8732f4 Mon Sep 17 00:00:00 2001 From: Jujhar Singh Date: Wed, 26 Aug 2020 19:14:54 +1200 Subject: [PATCH 1/3] Modify chrome.go to not rely on chrome stderr --- chrome.go | 66 ++++++++++++++++++++++++++++++++++++------------------- 1 file changed, 43 insertions(+), 23 deletions(-) diff --git a/chrome.go b/chrome.go index b17b803..aa3cb12 100644 --- a/chrome.go +++ b/chrome.go @@ -1,15 +1,14 @@ package lorca import ( - "bufio" "encoding/json" "errors" "fmt" - "io" "io/ioutil" "log" + "net" + "net/http" "os/exec" - "regexp" "sync" "sync/atomic" @@ -47,6 +46,24 @@ type chrome struct { bindings map[string]bindingFunc } +type browserVersion struct { + Browser string `json:"Browser"` + ProtocolVersion string `json:"Protocol-Version"` + UserAgent string `json:"User-Agent"` + V8Version string `json:"V8-Version"` + WebkitVersion string `json:"Webkit-Version"` + WebSocketDebuggerUrl string `json:"webSocketDebuggerUrl"` +} + +func getFreePort() (int, error) { + ln, err := net.Listen("tcp", "127.0.0.1:0") + if err != nil { + return 0, err + } + defer ln.Close() + return ln.Addr().(*net.TCPAddr).Port, nil +} + func newChromeWithArgs(chromeBinary string, args ...string) (*chrome, error) { // The first two IDs are used internally during the initialization c := &chrome{ @@ -55,24 +72,40 @@ func newChromeWithArgs(chromeBinary string, args ...string) (*chrome, error) { bindings: map[string]bindingFunc{}, } + debugPort, err := getFreePort() + if err != nil { + return nil, err + } + // Start chrome process + args = append(args, fmt.Sprintf("--remote-debugging-port=%d", debugPort)) c.cmd = exec.Command(chromeBinary, args...) - pipe, err := c.cmd.StderrPipe() + if err := c.cmd.Start(); err != nil { + return nil, err + } + + if err := c.cmd.Wait(); err != nil { + return nil, err + } + + res, err := http.Get(fmt.Sprintf("http://127.0.0.1:%d/json/version", debugPort)) if err != nil { return nil, err } - if err := c.cmd.Start(); err != nil { + + body, err := ioutil.ReadAll(res.Body) + if err != nil { return nil, err } - // Wait for websocket address to be printed to stderr - re := regexp.MustCompile(`^DevTools listening on (ws://.*?)\r?\n$`) - m, err := readUntilMatch(pipe, re) + browserVer := &browserVersion{} + + err = json.Unmarshal(body, &browserVer) if err != nil { - c.kill() return nil, err } - wsURL := m[1] + + wsURL := browserVer.WebSocketDebuggerUrl // Open a websocket c.ws, err = websocket.Dial(wsURL, "", "http://127.0.0.1") @@ -516,19 +549,6 @@ func (c *chrome) kill() error { return nil } -func readUntilMatch(r io.ReadCloser, re *regexp.Regexp) ([]string, error) { - br := bufio.NewReader(r) - for { - if line, err := br.ReadString('\n'); err != nil { - r.Close() - return nil, err - } else if m := re.FindStringSubmatch(line); m != nil { - go io.Copy(ioutil.Discard, br) - return m, nil - } - } -} - func contains(arr []string, x string) bool { for _, n := range arr { if x == n { From 7378c0fe9d85fec6a8dd2b3560925a9653999b04 Mon Sep 17 00:00:00 2001 From: Jujhar Singh Date: Wed, 26 Aug 2020 19:16:22 +1200 Subject: [PATCH 2/3] Remove --remote-debugging-port arg from ui.go This argument is now located in chrome.go --- ui.go | 1 - 1 file changed, 1 deletion(-) diff --git a/ui.go b/ui.go index bb4fa75..87f6bc1 100644 --- a/ui.go +++ b/ui.go @@ -76,7 +76,6 @@ func New(url, dir string, width, height int, customArgs ...string) (UI, error) { args = append(args, fmt.Sprintf("--user-data-dir=%s", dir)) args = append(args, fmt.Sprintf("--window-size=%d,%d", width, height)) args = append(args, customArgs...) - args = append(args, "--remote-debugging-port=0") chrome, err := newChromeWithArgs(ChromeExecutable(), args...) done := make(chan struct{}) From 25ec0987a9adf881f7d8897ac6ca45ebaae08944 Mon Sep 17 00:00:00 2001 From: Jujhar Singh Date: Wed, 26 Aug 2020 19:32:00 +1200 Subject: [PATCH 3/3] Remove c.cmd.Wait() --- chrome.go | 4 ---- 1 file changed, 4 deletions(-) diff --git a/chrome.go b/chrome.go index aa3cb12..0efc6ee 100644 --- a/chrome.go +++ b/chrome.go @@ -84,10 +84,6 @@ func newChromeWithArgs(chromeBinary string, args ...string) (*chrome, error) { return nil, err } - if err := c.cmd.Wait(); err != nil { - return nil, err - } - res, err := http.Get(fmt.Sprintf("http://127.0.0.1:%d/json/version", debugPort)) if err != nil { return nil, err