Chrome.cs
using System.Net;
using System.Runtime.Serialization.Json; using System.Text; using WebSocket4Net; namespace GenXdev.Helpers { public class Chrome { public static object padLock = new object(); const string JsonPostfix = "/json"; public string remoteDebuggingUri; public string sessionWSEndpoint; public int Port { get; private set; } public Chrome(string remoteDebuggingUri) { this.remoteDebuggingUri = remoteDebuggingUri; this.Port = (new Uri(this.remoteDebuggingUri)).Port; } public TRes SendRequest<TRes>() { HttpWebRequest req = (HttpWebRequest)WebRequest.Create(remoteDebuggingUri + JsonPostfix); var resp = req.GetResponse(); var respStream = resp.GetResponseStream(); StreamReader sr = new StreamReader(respStream); var s = sr.ReadToEnd(); resp.Dispose(); return Deserialise<TRes>(s); } public List<RemoteSessionsResponse> GetAvailableSessions() { var res = this.SendRequest<List<RemoteSessionsResponse>>(); return (from r in res where r.devtoolsFrontendUrl != null select r).ToList(); } public string NavigateTo(string uri) { // Page.navigate is working from M18 //var json = @"{""method"":""Page.navigate"",""params"":{""url"":""http://www.seznam.cz""},""id"":1}"; // Instead of Page.navigate, we can use document.location var json = @"{""method"":""Runtime.evaluate"",""params"":{""expression"":" + Serialization.ToJson("document.location='" + uri + "'") + @",""objectGroup"":""console"",""allowUnsafeEvalBlockedByCSP"":true,""includeCommandLineAPI"":true,""doNotPauseOnExceptions"":false,""returnByValue"":false},""id"":1}"; return this.SendCommand(json); } public string GetElementsByTagName(string tagName) { // Page.navigate is working from M18 //var json = @"{""method"":""Page.navigate"",""params"":{""url"":""http://www.seznam.cz""},""id"":1}"; // Instead of Page.navigate, we can use document.location var json = @"{""method"":""Runtime.evaluate"",""params"":{""expression"":""document.getElementsByTagName('" + tagName + @"')"",""objectGroup"":""console"",""allowUnsafeEvalBlockedByCSP"":true,""includeCommandLineAPI"":true,""doNotPauseOnExceptions"":false,""returnByValue"":false},""id"":1}"; return this.SendCommand(json); } public string Eval(string cmd) { return Eval(cmd, false); } public string GetEvalCommand(string cmd, bool allowTopLevelAwait = false) { string awaitParam = ""; if (allowTopLevelAwait) { awaitParam = @"""replMode"":true,"; } var json = @"{""method"":""Runtime.evaluate"",""params"":{""expression"":" + Serialization.ToJson(cmd) + @"," + awaitParam + @"""objectGroup"":""console"",""allowUnsafeEvalBlockedByCSP"":true,""includeCommandLineAPI"":true,""doNotPauseOnExceptions"":true,""returnByValue"":true},""id"":1}"; // return json; return json; } public string Eval(string cmd, bool allowTopLevelAwait = false, uint timeoutseconds = 30) { // return json; return this.SendCommand(GetEvalCommand(cmd, allowTopLevelAwait), timeoutseconds = 30); } public string SendCommand(string cmd, uint timeoutseconds = 30) { string ep; lock (Chrome.padLock) { ep = this.sessionWSEndpoint; } string message = ""; ManualResetEvent waitEvent = new ManualResetEvent(false); Exception exc = null; bool active = true; var t = new Thread(new ThreadStart(() => { try { WebSocket4Net.WebSocket j = new WebSocket4Net.WebSocket(ep); j.LocalEndPoint = new IPEndPoint(IPAddress.Loopback, 0); byte[] data; j.Opened += delegate (System.Object o, EventArgs e) { j.Send(cmd); }; j.MessageReceived += delegate (System.Object o, MessageReceivedEventArgs e) { message = e.Message; active = false; }; j.Error += delegate (System.Object o, SuperSocket.ClientEngine.ErrorEventArgs e) { active = false; exc = e.Exception; }; j.Closed += delegate (System.Object o, EventArgs e) { active = false; }; j.DataReceived += delegate (System.Object o, DataReceivedEventArgs e) { active = false; data = e.Data; }; j.Open(); System.DateTime startTime = System.DateTime.UtcNow; while (active && (System.DateTime.UtcNow - startTime).TotalSeconds < timeoutseconds && Thread.CurrentThread.ThreadState == ThreadState.Running) { Thread.Sleep(10); } try { if (j.State != WebSocket4Net.WebSocketState.Closed) { j.Close(); } } catch { } } finally { waitEvent.Set(); } })); t.Start(); waitEvent.WaitOne(); if (exc != null) throw exc; return message; } private T Deserialise<T>(string json) { T obj = Activator.CreateInstance<T>(); using (MemoryStream ms = new MemoryStream(Encoding.Unicode.GetBytes(json))) { DataContractJsonSerializer serializer = new DataContractJsonSerializer(obj.GetType()); obj = (T)serializer.ReadObject(ms); return obj; } } private T Deserialise<T>(Stream json) { T obj = Activator.CreateInstance<T>(); DataContractJsonSerializer serializer = new DataContractJsonSerializer(obj.GetType()); obj = (T)serializer.ReadObject(json); return obj; } public void SetActiveSession(string sessionWSEndpoint) { lock (padLock) // Sometimes binding to localhost might resolve wrong AddressFamily, force IPv4 this.sessionWSEndpoint = sessionWSEndpoint.Replace("ws://localhost", "ws://127.0.0.1").Replace("wss://localhost", "wss://127.0.0.1"); } } } |