📜 ⬆️ ⬇️

Instrumenting Google Chrome via the WebSocket API

image Interaction with browsers has never been a job for the faint of heart: about half a dozen different APIs, different IPC mechanisms, and different capabilities from different providers. Projects such as WebDriver , trying to abstract from this complexity, besides on the Web you can find dozens of other "headless" drivers using WebKit or other engines. Currently, even the W3C specification on WebDriver is in the works.

Google Chrome Instrumentation


However, while creating a common solution is a complex task, it turned out that Chrome instrumentation is very simple - as I recently discovered while researching some issues related to network delays. Starting with version 18, Chrome now supports remote debugging protocol v1.0 , which provides all the features of the browser using the usual WebSocket!
/Applications/Path To/Google Chrome --remote-debugging-port=9222 # OSX $> curl localhost:9222/json 

 [ { "devtoolsFrontendUrl": "/devtools/devtools.html?host=localhost:9222&page=1", "faviconUrl": "", "thumbnailUrl": "/thumb/chrome://newtab/", "title": "New Tab", "url": "chrome://newtab/", "webSocketDebuggerUrl": "ws://localhost:9222/devtools/page/1" } ] 

First, we enable remote debugging in Chrome (disabled by default). From now on, Chrome provides an HTTP server that allows you to control all open tabs. Each tab is an isolated process and, therefore, works with its WebSocket, the path to which is accessible through the attribute webSocketDebuggerUrl . Let's try to do something about it (translator's note: Ruby authoring code, but this is not fundamental):
 require 'em-http' require 'faye/websocket' require 'json' EM.run do # Chrome runs an HTTP handler listing available tabs conn = EM::HttpRequest.new('http://localhost:9222/json').get conn.callback do resp = JSON.parse(conn.response) puts "#{resp.size} available tabs, Chrome response: \n#{resp}" # connect to first tab via the WS debug URL ws = Faye::WebSocket::Client.new(resp.first['webSocketDebuggerUrl']) ws.onopen = lambda do |event| # once connected, enable network tracking ws.send JSON.dump({id: 1, method: 'Network.enable'}) # tell Chrome to navigate to twitter.com and look for "chrome" tweets ws.send JSON.dump({ id: 2, method: 'Page.navigate', params: {url: 'http://twitter.com/#!/search/chrome?q=chrome&' + rand(100).to_s} }) end ws.onmessage = lambda do |event| # print event notifications from Chrome to the console p [:new_message, JSON.parse(event.data)] end end end 


In this example, we tell Chrome to enable tracking and notification of network traffic, and then tell it to search Twitter. At the same time, Chrome will send us dozens of network notifications: initial page selection, notifications for each sub-resource, XHR, and so on (for example, the Network.responseReceived event ). In fact, if you leave the Web page open, you will also see long polling events generated for new tweets. Tons of information , all at your disposal.
')

Remote debugging (and more) with Chrome


The above example illustrates a very simple interaction with the Network API, but the protocol provides much more features. You can work with the JavaScript debugger, control the V8 virtual machine, modify and learn the DOM, and track the chronology of events, and more than half a dozen other features . Finally, although it’s cool to manage a desktop browser, browser management on your phone is even cooler: Chrome for Android provides all the same features .

Source: https://habr.com/ru/post/141981/


All Articles