Skip to content

Commit fcf7a0b

Browse files
committed
Support opening Chrome automatically on windows
1 parent a402e73 commit fcf7a0b

File tree

1 file changed

+81
-27
lines changed

1 file changed

+81
-27
lines changed

lib/debug/server_cdp.rb

Lines changed: 81 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,15 @@
77
require 'stringio'
88
require 'open3'
99
require 'tmpdir'
10+
require 'tempfile'
1011

1112
module DEBUGGER__
1213
module UI_CDP
1314
SHOW_PROTOCOL = ENV['RUBY_DEBUG_CDP_SHOW_PROTOCOL'] == '1'
1415

16+
class UnsupportedError < StandardError; end
17+
class NotFoundChromeEndpointError < StandardError; end
18+
1519
class << self
1620
def setup_chrome addr
1721
return if CONFIG[:chrome_path] == ''
@@ -59,46 +63,96 @@ def setup_chrome addr
5963
end
6064
end
6165
pid
62-
rescue Errno::ENOENT
66+
rescue Errno::ENOENT, UnsupportedError, NotFoundChromeEndpointError
6367
nil
6468
end
6569

66-
def get_chrome_path
67-
return CONFIG[:chrome_path] if CONFIG[:chrome_path]
70+
def run_new_chrome
71+
path = CONFIG[:chrome_path]
6872

69-
# The process to check OS is based on `selenium` project.
73+
data = nil
74+
port = nil
75+
wait_thr = nil
7076
case RbConfig::CONFIG['host_os']
7177
when /mswin|msys|mingw|cygwin|emc/
72-
'C:\Program Files (x86)\Google\Chrome\Application\chrome.exe'
78+
if path.nil?
79+
candidates = ['C:\\Program Files (x86)\\Google\\Chrome\\Application\\chrome.exe', 'C:\\Program Files\\Google\\Chrome\\Application\\chrome.exe']
80+
path = get_chrome_path candidates
81+
end
82+
uuid = SecureRandom.uuid
83+
# The path is based on https://github.com/sindresorhus/open/blob/v8.4.0/index.js#L128.
84+
stdin, stdout, stderr, wait_thr = *Open3.popen3("#{ENV['SystemRoot']}\\System32\\WindowsPowerShell\\v1.0\\powershell")
85+
tf = Tempfile.create(['debug-', '.txt'])
86+
87+
stdin.puts("Start-process '#{path}' -Argumentlist '--remote-debugging-port=0', '--no-first-run', '--no-default-browser-check', '--user-data-dir=C:\\temp' -Wait -RedirectStandardError #{tf.path}")
88+
stdin.close
89+
stdout.close
90+
stderr.close
91+
port, path = get_devtools_endpoint(tf.path)
92+
93+
at_exit{
94+
CONFIG.skip_all
95+
stdin, stdout, stderr, wait_thr = *Open3.popen3("#{ENV['SystemRoot']}\\System32\\WindowsPowerShell\\v1.0\\powershell")
96+
stdin.puts("Stop-process -Name chrome")
97+
stdin.close
98+
stdout.close
99+
stderr.close
100+
tf.close
101+
begin
102+
File.unlink(tf)
103+
rescue Errno::EACCES
104+
end
105+
}
73106
when /darwin|mac os/
74-
'/Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome'
75-
when /linux/
76-
'google-chrome'
107+
path = path || '/Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome'
108+
dir = Dir.mktmpdir
109+
# The command line flags are based on: https://developer.mozilla.org/en-US/docs/Tools/Remote_Debugging/Chrome_Desktop#connecting.
110+
stdin, stdout, stderr, wait_thr = *Open3.popen3("#{path} --remote-debugging-port=0 --no-first-run --no-default-browser-check --user-data-dir=#{dir}")
111+
stdin.close
112+
stdout.close
113+
data = stderr.readpartial 4096
114+
stderr.close
115+
if data.match /DevTools listening on ws:\/\/127.0.0.1:(\d+)(.*)/
116+
port = $1
117+
path = $2
118+
end
119+
120+
at_exit{
121+
CONFIG.skip_all
122+
FileUtils.rm_rf dir
123+
}
77124
else
78-
raise "Unsupported OS"
125+
raise UnsupportedError
79126
end
80-
end
81127

82-
def run_new_chrome
83-
dir = Dir.mktmpdir
84-
# The command line flags are based on: https://developer.mozilla.org/en-US/docs/Tools/Remote_Debugging/Chrome_Desktop#connecting
85-
stdin, stdout, stderr, wait_thr = *Open3.popen3("#{get_chrome_path} --remote-debugging-port=0 --no-first-run --no-default-browser-check --user-data-dir=#{dir}")
86-
stdin.close
87-
stdout.close
88-
89-
data = stderr.readpartial 4096
90-
if data.match /DevTools listening on ws:\/\/127.0.0.1:(\d+)(.*)/
91-
port = $1
92-
path = $2
93-
end
94-
stderr.close
128+
[port, path, wait_thr.pid]
129+
end
95130

96-
at_exit{
97-
DEBUGGER__.skip_all
98-
FileUtils.rm_rf dir
131+
def get_chrome_path candidates
132+
candidates.each{|c|
133+
if File.exist? c
134+
return c
135+
end
99136
}
137+
raise UnsupportedError
138+
end
100139

101-
[port, path, wait_thr.pid]
140+
ITERATIONS = 50
141+
142+
def get_devtools_endpoint tf
143+
i = 1
144+
while i < ITERATIONS
145+
i += 1
146+
if File.exist?(tf) && data = File.read(tf)
147+
if data.match /DevTools listening on ws:\/\/127.0.0.1:(\d+)(.*)/
148+
port = $1
149+
path = $2
150+
return [port, path]
151+
end
152+
end
153+
sleep 0.1
154+
end
155+
raise NotFoundChromeEndpointError
102156
end
103157
end
104158

0 commit comments

Comments
 (0)