/// <summary>
        /// Sets the proxy server for the specified <see cref="IRequestContext"/>
        /// </summary>
        /// <param name="requestContext">request context</param>
        /// <param name="scheme">is the protocol of the proxy server, and is one of: 'http', 'socks', 'socks4', 'socks5'. Also note that 'socks' is equivalent to 'socks5'.</param>
        /// <param name="host">proxy host</param>
        /// <param name="port">proxy port</param>
        /// <returns>returns <see cref="SetPreferenceResponse.Success"/> true if successfull, false otherwise.</returns>
        /// <remarks>Internally calls <seealso cref="IRequestContext.SetPreference(string, object, out string)"/> with
        /// preference 'proxy' and mode of 'fixed_servers'</remarks>
        public static Task <SetProxyResponse> SetProxyAsync(this IRequestContext requestContext, string scheme, string host, int?port)
        {
            if (CefThread.HasShutdown)
            {
                return(Task.FromResult(new SetProxyResponse(false, "Cef.Shutdown has already been called, it is no longer possible to call SetProxyAsync.")));
            }

            Func <SetProxyResponse> func = () =>
            {
                string error;
                bool   success = false;

                if (requestContext.CanSetPreference("proxy"))
                {
                    var v = GetProxyDictionary(scheme, host, port);

                    success = requestContext.SetPreference("proxy", v, out error);
                }
                else
                {
                    error = "Unable to set the proxy preference, it is read-only. If you specified the proxy settings with command line args it is not possible to change the proxy settings via this method.";
                }

                return(new SetProxyResponse(success, error));
            };

            if (CefThread.CurrentlyOnUiThread)
            {
                return(Task.FromResult(func()));
            }

            return(CefThread.ExecuteOnUiThread(func));
        }
Пример #2
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);
        }
Пример #3
0
        /// <summary>
        /// Set the value associated with preference name. If value is null the
        /// preference will be restored to its default value. If setting the preference
        /// fails then error will be populated with a detailed description of the
        /// problem. This method must be called on the CEF UI thread.
        /// Preferences set via the command-line usually cannot be modified.
        /// </summary>
        /// <param name="name">preference key</param>
        /// <param name="value">preference value</param>
        /// <param name="error">out error</param>
        /// <returns>Returns true if the value is set successfully and false otherwise.</returns>
        /// <remarks>Use Cef.UIThreadTaskFactory to execute this method if required,
        /// <see cref="IBrowserProcessHandler.OnContextInitialized"/> and ChromiumWebBrowser.IsBrowserInitializedChanged are both
        /// executed on the CEF UI thread, so can be called directly.
        /// When CefSettings.MultiThreadedMessageLoop == false (the default is true) then the main
        /// application thread will be the CEF UI thread.</remarks>
        public static Task <SetPreferenceResponse> SetPreferenceAsync(this IRequestContext requestContext, string name, object value)
        {
            if (CefThread.HasShutdown)
            {
                return(Task.FromResult(new SetPreferenceResponse(false, "Cef.Shutdown has already been called, it is no longer possible to call SetPreferenceAsync.")));
            }

            Func <SetPreferenceResponse> func = () =>
            {
                string error;
                var    success = requestContext.SetPreference(name, value, out error);

                return(new SetPreferenceResponse(success, error));
            };

            if (CefThread.CurrentlyOnUiThread)
            {
                return(Task.FromResult(func()));
            }

            return(CefThread.ExecuteOnUiThread(func));
        }
Пример #4
0
        /// <summary>
        /// Execute a method call over the DevTools protocol. This is a more structured
        /// version of SendDevToolsMessage. <see cref="ExecuteDevToolsMethod"/> can only be called on the
        /// CEF UI Thread, 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.
        /// See the SendDevToolsMessage documentation for additional usage information.
        /// </summary>
        /// <param name="browser">the browser instance</param>
        /// <param name="messageId">is an incremental number that uniquely identifies the message (pass 0 to have the next number assigned
        /// automatically based on previous values)</param>
        /// <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 assigned message Id. If the message was
        /// unsuccessfully submitted for validation, this value will be 0.</returns>
        public static Task <int> ExecuteDevToolsMethodAsync(this IBrowser browser, int messageId, string method, IDictionary <string, object> parameters = null)
        {
            WebBrowserExtensions.ThrowExceptionIfBrowserNull(browser);

            var browserHost = browser.GetHost();

            WebBrowserExtensions.ThrowExceptionIfBrowserHostNull(browserHost);

            if (CefThread.CurrentlyOnUiThread)
            {
                return(Task.FromResult(browserHost.ExecuteDevToolsMethod(messageId, method, parameters)));
            }

            if (CefThread.CanExecuteOnUiThread)
            {
                return(CefThread.ExecuteOnUiThread(() =>
                {
                    return browserHost.ExecuteDevToolsMethod(messageId, method, parameters);
                }));
            }

            //CEF returns 0 to signify failure, we'll do the same.
            return(Task.FromResult(0));
        }
Пример #5
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>
        /// <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);
        }
Пример #6
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>
        /// <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);
        }