module DEBUGGER__::UI_CDP
Constants
- INVALID_REQUEST
- SHOW_PROTOCOL
Public Class Methods
get_chrome_path()
click to toggle source
# File debug-1.4.0/lib/debug/server_cdp.rb, line 55 def get_chrome_path return CONFIG[:chrome_path] if CONFIG[:chrome_path] # The process to check OS is based on `selenium` project. case RbConfig::CONFIG['host_os'] when /mswin|msys|mingw|cygwin|emc/ 'C:\Program Files (x86)\Google\Chrome\Application\chrome.exe' when /darwin|mac os/ '/Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome' when /linux/ 'google-chrome' else raise "Unsupported OS" end end
run_new_chrome()
click to toggle source
# File debug-1.4.0/lib/debug/server_cdp.rb, line 71 def run_new_chrome dir = Dir.mktmpdir # The command line flags are based on: https://developer.mozilla.org/en-US/docs/Tools/Remote_Debugging/Chrome_Desktop#connecting 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}") stdin.close stdout.close data = stderr.readpartial 4096 if data.match /DevTools listening on ws:\/\/127.0.0.1:(\d+)(.*)/ port = $1 path = $2 end stderr.close at_exit{ CONFIG[:skip_path] = [//] # skip all FileUtils.rm_rf dir } [port, path, wait_thr.pid] end
setup_chrome(addr)
click to toggle source
# File debug-1.4.0/lib/debug/server_cdp.rb, line 16 def setup_chrome addr return if CONFIG[:chrome_path] == '' port, path, pid = run_new_chrome begin s = Socket.tcp '127.0.0.1', port rescue Errno::ECONNREFUSED, Errno::EADDRNOTAVAIL return end ws_client = WebSocketClient.new(s) ws_client.handshake port, path ws_client.send id: 1, method: 'Target.getTargets' 4.times do res = ws_client.extract_data case when res['id'] == 1 && target_info = res.dig('result', 'targetInfos') page = target_info.find{|t| t['type'] == 'page'} ws_client.send id: 2, method: 'Target.attachToTarget', params: { targetId: page['targetId'], flatten: true } when res['id'] == 2 s_id = res.dig('result', 'sessionId') sleep 0.1 ws_client.send sessionId: s_id, id: 1, method: 'Page.navigate', params: { url: "devtools://devtools/bundled/inspector.html?ws=#{addr}" } end end pid rescue Errno::ENOENT nil end
Public Instance Methods
activate_bp(bps)
click to toggle source
# File debug-1.4.0/lib/debug/server_cdp.rb, line 458 def activate_bp bps bps.each_key{|k| if k.match /^\d+:(\d+):(.*)/ line = $1 path = $2 SESSION.add_line_breakpoint(path, line.to_i + 1) else SESSION.add_catch_breakpoint 'Exception' end } end
cleanup_reader()
click to toggle source
# File debug-1.4.0/lib/debug/server_cdp.rb, line 475 def cleanup_reader Process.kill :KILL, @chrome_pid if @chrome_pid end
deactivate_bp()
click to toggle source
# File debug-1.4.0/lib/debug/server_cdp.rb, line 470 def deactivate_bp @q_msg << 'del' @q_ans << 'y' end
del_bp(bps, k)
click to toggle source
# File debug-1.4.0/lib/debug/server_cdp.rb, line 441 def del_bp bps, k return bps unless idx = bps[k] bps.delete k bps.each_key{|i| bps[i] -= 1 if bps[i] > idx} @q_msg << "del #{idx}" bps end
fire_event(event, **result)
click to toggle source
# File debug-1.4.0/lib/debug/server_cdp.rb, line 495 def fire_event event, **result if result.empty? send_event event else send_event event, **result end end
get_source_code(path)
click to toggle source
# File debug-1.4.0/lib/debug/server_cdp.rb, line 450 def get_source_code path return @src_map[path] if @src_map[path] src = File.read(path) @src_map[path] = src src end
process()
click to toggle source
# File debug-1.4.0/lib/debug/server_cdp.rb, line 263 def process bps = {} @src_map = {} loop do req = @ws_server.extract_data $stderr.puts '[>]' + req.inspect if SHOW_PROTOCOL case req['method'] ## boot/configuration when 'Page.getResourceTree' path = File.absolute_path($0) src = File.read(path) @src_map[path] = src send_response req, frameTree: { frame: { id: SecureRandom.hex(16), loaderId: SecureRandom.hex(16), url: 'http://debuggee/', securityOrigin: 'http://debuggee', mimeType: 'text/plain' }, resources: [ ] } send_event 'Debugger.scriptParsed', scriptId: path, url: "http://debuggee#{path}", startLine: 0, startColumn: 0, endLine: src.count("\n"), endColumn: 0, executionContextId: 1, hash: src.hash send_event 'Runtime.executionContextCreated', context: { id: SecureRandom.hex(16), origin: "http://#{@addr}", name: '' } when 'Debugger.getScriptSource' s_id = req.dig('params', 'scriptId') src = get_source_code s_id send_response req, scriptSource: src @q_msg << req when 'Page.startScreencast', 'Emulation.setTouchEmulationEnabled', 'Emulation.setEmitTouchEventsForMouse', 'Runtime.compileScript', 'Page.getResourceContent', 'Overlay.setPausedInDebuggerMessage', 'Runtime.releaseObjectGroup', 'Runtime.discardConsoleEntries', 'Log.clear' send_response req ## control when 'Debugger.resume' @q_msg << 'c' @q_msg << req send_response req send_event 'Debugger.resumed' when 'Debugger.stepOver' begin @session.check_postmortem @q_msg << 'n' send_response req send_event 'Debugger.resumed' rescue PostmortemError send_fail_response req, code: INVALID_REQUEST, message: "'stepOver' is not supported while postmortem mode" ensure @q_msg << req end when 'Debugger.stepInto' begin @session.check_postmortem @q_msg << 's' send_response req send_event 'Debugger.resumed' rescue PostmortemError send_fail_response req, code: INVALID_REQUEST, message: "'stepInto' is not supported while postmortem mode" ensure @q_msg << req end when 'Debugger.stepOut' begin @session.check_postmortem @q_msg << 'fin' send_response req send_event 'Debugger.resumed' rescue PostmortemError send_fail_response req, code: INVALID_REQUEST, message: "'stepOut' is not supported while postmortem mode" ensure @q_msg << req end when 'Debugger.setSkipAllPauses' skip = req.dig('params', 'skip') if skip deactivate_bp else activate_bp bps end send_response req # breakpoint when 'Debugger.getPossibleBreakpoints' s_id = req.dig('params', 'start', 'scriptId') line = req.dig('params', 'start', 'lineNumber') src = get_source_code s_id end_line = src.count("\n") line = end_line if line > end_line send_response req, locations: [ { scriptId: s_id, lineNumber: line, } ] when 'Debugger.setBreakpointByUrl' line = req.dig('params', 'lineNumber') url = req.dig('params', 'url') locations = [] if url.match /http:\/\/debuggee(.*)/ path = $1 cond = req.dig('params', 'condition') src = get_source_code path end_line = src.count("\n") line = end_line if line > end_line b_id = "1:#{line}:#{path}" if cond != '' SESSION.add_line_breakpoint(path, line + 1, cond: cond) else SESSION.add_line_breakpoint(path, line + 1) end bps[b_id] = bps.size locations << {scriptId: path, lineNumber: line} else b_id = "1:#{line}:#{url}" end send_response req, breakpointId: b_id, locations: locations when 'Debugger.removeBreakpoint' b_id = req.dig('params', 'breakpointId') bps = del_bp bps, b_id send_response req when 'Debugger.setBreakpointsActive' active = req.dig('params', 'active') if active activate_bp bps else deactivate_bp # TODO: Change this part because catch breakpoints should not be deactivated. end send_response req when 'Debugger.setPauseOnExceptions' state = req.dig('params', 'state') ex = 'Exception' case state when 'none' @q_msg << 'config postmortem = false' bps = del_bp bps, ex when 'uncaught' @q_msg << 'config postmortem = true' bps = del_bp bps, ex when 'all' @q_msg << 'config postmortem = false' SESSION.add_catch_breakpoint ex bps[ex] = bps.size end send_response req when 'Debugger.evaluateOnCallFrame', 'Runtime.getProperties' @q_msg << req end end rescue Detach @q_msg << 'continue' end
puts(result)
click to toggle source
# File debug-1.4.0/lib/debug/server_cdp.rb, line 507 def puts result # STDERR.puts "puts: #{result}" # send_event 'output', category: 'stderr', output: "PUTS!!: " + result.to_s end
readline(prompt)
click to toggle source
Called by the SESSION thread
# File debug-1.4.0/lib/debug/server_cdp.rb, line 481 def readline prompt return 'c' unless @q_msg @q_msg.pop || 'kill!' end
respond(req, **result)
click to toggle source
# File debug-1.4.0/lib/debug/server_cdp.rb, line 487 def respond req, **result send_response req, **result end
respond_fail(req, **result)
click to toggle source
# File debug-1.4.0/lib/debug/server_cdp.rb, line 491 def respond_fail req, **result send_fail_response req, **result end
send_event(method, **params)
click to toggle source
# File debug-1.4.0/lib/debug/server_cdp.rb, line 253 def send_event method, **params if params.empty? @ws_server.send method: method, params: {} else @ws_server.send method: method, params: params end end
send_fail_response(req, **res)
click to toggle source
# File debug-1.4.0/lib/debug/server_cdp.rb, line 249 def send_fail_response req, **res @ws_server.send id: req['id'], error: res end
send_response(req, **res)
click to toggle source
# File debug-1.4.0/lib/debug/server_cdp.rb, line 241 def send_response req, **res if res.empty? @ws_server.send id: req['id'], result: {} else @ws_server.send id: req['id'], result: res end end
sock(skip: false) { |$stderr| ... }
click to toggle source
# File debug-1.4.0/lib/debug/server_cdp.rb, line 503 def sock skip: false yield $stderr end