Пример #1
0
        /// <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>
        /// <typeparam name="T">The type into which the result will be deserialzed.</typeparam>
        /// <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 Task <T> ExecuteDevToolsMethodAsync <T>(string method, IDictionary <string, object> parameters = null) where T : DevToolsDomainResponseBase
        {
            if (browser == null || browser.IsDisposed)
            {
                //TODO: Queue up commands where possible
                throw new ObjectDisposedException(nameof(IBrowser));
            }

            var messageId = Interlocked.Increment(ref lastMessageId);

            var taskCompletionSource = new TaskCompletionSource <T>();

            var methodResultContext = new DevToolsMethodResponseContext(
                type: typeof(T),
                setResult: o => taskCompletionSource.TrySetResult((T)o),
                setException: taskCompletionSource.TrySetException,
                syncContext: CaptureSyncContext ? SynchronizationContext.Current : SyncContext
                );

            if (!queuedCommandResults.TryAdd(messageId, methodResultContext))
            {
                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)
            {
                ExecuteDevToolsMethod(browserHost, messageId, method, parameters, methodResultContext);
            }
            //ExecuteDevToolsMethod can only be called on the CEF UI Thread
            else if (CefThread.CanExecuteOnUiThread)
            {
                CefThread.ExecuteOnUiThread(() =>
                {
                    ExecuteDevToolsMethod(browserHost, messageId, method, parameters, methodResultContext);
                    return((object)null);
                });
            }
            else
            {
                queuedCommandResults.TryRemove(messageId, out methodResultContext);
                throw new DevToolsClientException("Unable to invoke ExecuteDevToolsMethod on CEF UI Thread.");
            }

            return(taskCompletionSource.Task);
        }
Пример #2
0
 private void ExecuteDevToolsMethod(IBrowserHost browserHost, int messageId, string method, IDictionary <string, object> parameters, DevToolsMethodResponseContext methodResultContext)
 {
     try
     {
         var returnedMessageId = browserHost.ExecuteDevToolsMethod(messageId, method, parameters);
         if (returnedMessageId == 0)
         {
             throw new DevToolsClientException(string.Format("Failed to execute dev tools method {0}.", method));
         }
         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));
         }
     }
     catch (Exception ex)
     {
         queuedCommandResults.TryRemove(messageId, out _);
         methodResultContext.SetException(ex);
     }
 }