void IDevToolsMessageObserver.OnDevToolsMethodResult(IBrowser browser, int messageId, bool success, Stream result) { var uiThread = CefThread.CurrentlyOnUiThread; SyncContextTaskCompletionSource <DevToolsMethodResponse> taskCompletionSource = null; if (queuedCommandResults.TryRemove(messageId, out taskCompletionSource)) { var methodResult = new DevToolsMethodResponse { Success = success, MessageId = messageId }; //TODO: Improve this var memoryStream = new MemoryStream((int)result.Length); result.CopyTo(memoryStream); methodResult.ResponseAsJsonString = Encoding.UTF8.GetString(memoryStream.ToArray()); Action execute = null; if (success) { execute = () => { taskCompletionSource.TrySetResult(methodResult); }; } else { execute = () => { var errorObj = methodResult.DeserializeJson <DevToolsDomainErrorResponse>(); errorObj.MessageId = messageId; //Make sure continuation runs on Thread Pool taskCompletionSource.TrySetException(new DevToolsClientException("DevTools Client Error :" + errorObj.Message, errorObj)); }; } var syncContext = taskCompletionSource.SyncContext; if (syncContext == null) { execute(); } else { syncContext.Post(new SendOrPostCallback((o) => { execute(); }), null); } } }
/// <summary> /// Execute a method call over the DevTools protocol. This method can be called on any thread. /// See the DevTools protocol documentation at https://chromedevtools.github.io/devtools-protocol/ for details /// of supported methods and the expected <paramref name="parameters"/> dictionary contents. /// </summary> /// <param name="method">is the method name</param> /// <param name="parameters">are the method parameters represented as a dictionary, /// which may be empty.</param> /// <returns>return a Task that can be awaited to obtain the method result</returns> public async Task <DevToolsMethodResponse> ExecuteDevToolsMethodAsync(string method, IDictionary <string, object> parameters = null) { if (browser == null || browser.IsDisposed) { //TODO: Queue up commands where possible return(new DevToolsMethodResponse { Success = false }); } var messageId = Interlocked.Increment(ref lastMessageId); var taskCompletionSource = new SyncContextTaskCompletionSource <DevToolsMethodResponse>(); taskCompletionSource.SyncContext = CaptureSyncContext ? SynchronizationContext.Current : syncContext; if (!queuedCommandResults.TryAdd(messageId, taskCompletionSource)) { throw new DevToolsClientException(string.Format("Unable to add MessageId {0} to queuedCommandResults ConcurrentDictionary.", messageId)); } var browserHost = browser.GetHost(); //Currently on CEF UI Thread we can directly execute if (CefThread.CurrentlyOnUiThread) { var returnedMessageId = browserHost.ExecuteDevToolsMethod(messageId, method, parameters); if (returnedMessageId == 0) { return(new DevToolsMethodResponse { Success = false }); } else if (returnedMessageId != messageId) { //For some reason our message Id's don't match throw new DevToolsClientException(string.Format("Generated MessageId {0} doesn't match returned Message Id {1}", returnedMessageId, messageId)); } } //ExecuteDevToolsMethod can only be called on the CEF UI Thread else if (CefThread.CanExecuteOnUiThread) { var returnedMessageId = await CefThread.ExecuteOnUiThread(() => { return(browserHost.ExecuteDevToolsMethod(messageId, method, parameters)); }).ConfigureAwait(false); if (returnedMessageId == 0) { return(new DevToolsMethodResponse { Success = false }); } else if (returnedMessageId != messageId) { //For some reason our message Id's don't match throw new DevToolsClientException(string.Format("Generated MessageId {0} doesn't match returned Message Id {1}", returnedMessageId, messageId)); } } else { throw new DevToolsClientException("Unable to invoke ExecuteDevToolsMethod on CEF UI Thread."); } return(await taskCompletionSource.Task); }
/// <summary> /// Execute a method call over the DevTools protocol. This method can be called on any thread. /// See the DevTools protocol documentation at https://chromedevtools.github.io/devtools-protocol/ for details /// of supported methods and the expected <paramref name="parameters" /> dictionary contents. /// </summary> /// <param name="method">is the method name</param> /// <param name="parameters">are the method parameters represented as a dictionary, /// which may be empty.</param> /// <returns>return a Task that can be awaited to obtain the method result</returns> public new async Task <DevToolsMethodResponse> ExecuteDevToolsMethodAsync(string method, IDictionary <string, object> parameters = null) { DevToolsMethodResponse result; if (this.browser == null || this.browser.IsDisposed) { result = new DevToolsMethodResponse { Success = false }; } else { int messageId = Interlocked.Increment(ref this.lastMessageId); SyncContextTaskCompletionSource <DevToolsMethodResponse> syncContextTaskCompletionSource = new SyncContextTaskCompletionSource <DevToolsMethodResponse>(); syncContextTaskCompletionSource.SyncContext = (this.CaptureSyncContext ? SynchronizationContext.Current : this.syncContext); if (!this.queuedCommandResults.TryAdd(messageId, syncContextTaskCompletionSource)) { throw new DevToolsClientException(string.Format("Unable to add MessageId {0} to queuedCommandResults ConcurrentDictionary.", messageId)); } IBrowserHost browserHost = this.browser.GetHost(); if (CefThread.CurrentlyOnUiThread) { int num = browserHost.ExecuteDevToolsMethod(messageId, method, parameters); if (num == 0) { result = new DevToolsMethodResponse { Success = false }; return(result); } if (num != messageId) { throw new DevToolsClientException(string.Format("Generated MessageId {0} doesn't match returned Message Id {1}", num, messageId)); } } else { if (!CefThread.CanExecuteOnUiThread) { throw new DevToolsClientException("Unable to invoke ExecuteDevToolsMethod on CEF UI Thread."); } int num2 = await CefThread.ExecuteOnUiThread <int>(() => browserHost.ExecuteDevToolsMethod(messageId, method, parameters)).ConfigureAwait(false); if (num2 == 0) { result = new DevToolsMethodResponse { Success = false }; return(result); } if (num2 != messageId) { // throw new DevToolsClientException(string.Format("1Generated MessageId {0} doesn't match returned Message Id {1}", num2, messageId)); } } result = await syncContextTaskCompletionSource.Task; } return(result); }