Remote DOM modifications

293 views
Skip to first unread message

AlexVN

unread,
Jan 10, 2012, 11:40:42 AM1/10/12
to Google Chrome Developer Tools
I'm creating a small application that should remotelly control the
browser window: navigate, fill forms, etc. I'm trying to archive the
goal using Chrome Remote Debugging and C#. Currently the prototype
connnects to browser, get the list of available pages and establish
WebSocket connection.

1. Start chrome.exe --remote-debugging-port=9123
2. Connecto to ws://localhost:9123/devtools/page/1 and send:
request: { "id": 1, "method": "DOM.setOuterHTML", "params": {"nodeId":
1, "outerHTML": ""}}

It looks wrong but no error is returned.


Code:
var client = new WebClient();
var pages = client.DownloadString("http://localhost:9123/
json");
Console.WriteLine(pages); // works well, displays JSON
with info about pages

// create WebSocket
var socket = new WebSockets.WebSocket("ws://localhost:9123/
devtools/page/1");
// it should print messages to console:
socket.OnMessage += (sender, eventdata) =>
Console.WriteLine(eventdata);

// works well - sends and recieves handshaking messages
socket.Connect();

Console.WriteLine("\nType \"exit\" to exit.\n");

string data;
while (true)
{
Thread.Sleep(500);
Console.Write("> ");
data = Console.ReadLine();
if (data == "exit")
break;
// sends data:
socket.Send(data);
}

How data is sending into the WebSocket stream:
byte[] dataBuffer = Encoding.UTF8.GetBytes(data);
_wsStream.WriteByte(0x00);
_wsStream.Write(dataBuffer, 0, dataBuffer.Length);
_wsStream.WriteByte(0xff);

And the reading never returns:
private void Message() // started in different thread
{
while (_readyState == WsState.Open)
{
string data = Receive(); // does _wsStream.ReadByte();
and stops on it forever
var handler = OnMessage;
if (null != handler && data != null)
handler(this, data);
}
}

Could you please help me with the command syntax and troubleshootings
the issue...

Thanks,
Alex

pfeldman

unread,
Jan 10, 2012, 12:30:31 PM1/10/12
to Google Chrome Developer Tools
You should not use node handles (ids) that were not provided to you by
the backend. You should first issue DOM.getDocument request to get the
document, then you can mutate its nodes. Note that setting outer html
for document node (<html>) is not currently supported, so you should
only modify <head>, <body> or their descendants. I am currently
working on getting setOuterHTML for <html> node fixed.

If you'd like to feed entire document to the backend, you could
instead issue Runtime.evaluate({"expression":
"document.write('<escaped html here>'); document.close();"})

Pavel

AlexVN

unread,
Jan 11, 2012, 8:43:19 AM1/11/12
to Google Chrome Developer Tools
Thank you for the response, Pavel!

I've modified the code in the following way:

var socket = new WebSockets.WebSocket("ws://localhost:9123/
devtools/page/1");
socket.OnMessage += (sender, eventdata) =>
Console.WriteLine(">> " + eventdata);
socket.OnError += (sender, eventdata) =>
Console.WriteLine(">> ERROR: " + eventdata);
socket.OnOpen += (sender, e) => Console.WriteLine(">>>
Connected to socket");
socket.OnClose += (sender, e) => Console.WriteLine(">>>
Connection closed");
socket.Connect();

const string getDocumentRequest = "request: {\"id\": 0,
\"method\": \"DOM.getDocument\"}";

Console.WriteLine(getDocumentRequest);
socket.Send(getDocumentRequest);

Console.WriteLine(getDocumentRequest);
socket.Send(getDocumentRequest);

And it gives me the following log:

[ {
"devtoolsFrontendUrl": "/devtools/devtools.html?host=localhost:
9123&page=1",
"faviconUrl": "https://mail.google.com/mail/images/favicon.ico",
"thumbnailUrl": "/thumb/https://mail.google.com/mail/?shva=1***",
"title": "Gmail - Remote DOM modifications - ***",
"url": "https://mail.google.com/mail/?shva=1***",
"webSocketDebuggerUrl": "ws://localhost:9123/devtools/page/1"
}, {
"devtoolsFrontendUrl": "/devtools/devtools.html?host=localhost:
9123&page=2",
"faviconUrl": "http://groups.google.com/groups/img/3/favicon.ico",
"thumbnailUrl": "/thumb/http://groups.google.com/group/google-
chrome-develope
r-tools/browse_thread/thread/3c07878f68010425/d7b75570a0881ebf?
show_docid=d7b755
70a0881ebf&pli=1",
"title": "Remote DOM modifications - Google Chrome Developer Tools
| Google G
roups",
"url": "http://groups.google.com/group/google-chrome-developer-
tools/browse_t
hread/thread/3c07878f68010425/d7b75570a0881ebf?
show_docid=d7b75570a0881ebf&pli=1
",
"webSocketDebuggerUrl": "ws://localhost:9123/devtools/page/2"
} ]

>>> Connected to socket
request: {"id": 0, "method": "DOM.getDocument"}
request: {"id": 0, "method": "DOM.getDocument"}
>> ERROR: Unable to read data from the transport connection: An existing connect
ion was forcibly closed by the remote host.
>> ERROR: Unable to write data to the transport connection: An existing connecti
on was forcibly closed by the remote host.

Type "exit" to exit.

>>> Connection closed
>

The following happens:
1. Application gets the list of pages from the browser by sending the
HTTP request to localhost:9123
2. Then it creates WebSoket connection (sends Connection: Upgrade and
recieves response)
3. Then it sends the "request: {\"id\": 0, \"method\":
\"DOM.getDocument\"}" into the socket and the browser terminates the
connection so the send sending of the same request throws the
exception.

Thank you for the help!

Regards,
Alex

AlexVN

unread,
Jan 11, 2012, 2:05:51 PM1/11/12
to Google Chrome Developer Tools
Still cannot make it work...

I've replaced the WebSocket library with http://websocket4net.codeplex.com/

and created a very simple HTML page:
<script>
setInterval(function () { console.log('!'); }, 1000);
</script>

The program is very simple:
var client = new WebClient();
var pages = client.DownloadString("http://127.0.0.1:9123/
json");
Console.WriteLine(pages);

var socket = new WebSocket("ws://127.0.0.1:9123/devtools/
page/1", WebSocketVersion.DraftHybi10);
socket.MessageReceived += (sender, e) =>
Console.WriteLine(">> " + e.Message);
socket.DataReceived += (sender, e) =>
Console.WriteLine(">> " + e.Data.Length);
socket.Error += (sender, e) => Console.WriteLine(">> " +
e.Exception.Message);
socket.Closed += (sender, e) => Console.WriteLine(">>
Closed");
socket.Opened += (sender, e) => Console.WriteLine(">>
Opened");
socket.Open();

Console.WriteLine("\nType \"exit\" to exit.\n");

string data;
while (true)
{
Thread.Sleep(500);
Console.Write("> ");
data = Console.ReadLine();
if (data == "exit")
break;
socket.Send(data);
}

I'm expecting several log messages recieved in this WebSocket as
http://code.google.com/chrome/devtools/docs/protocol/0.1/console.html
describes.

Whatever I do, the connection dies after the first message:
[ {
"devtoolsFrontendUrl": "/devtools/devtools.html?
host=127.0.0.1:9123&page=1",
"faviconUrl": "",
"thumbnailUrl": "/thumb/file:///D:/!/test.html",
"title": "",
"url": "file:///D:/!/test.html",
"webSocketDebuggerUrl": "ws://127.0.0.1:9123/devtools/page/1"
}]


Type "exit" to exit.

>> Opened
> request:{"id":1,"method":"Console.clearMessages"}
>> Closed
>

Any ideas?



Reply all
Reply to author
Forward
0 new messages