/// <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)); }
/// <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); }
/// <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)); }
/// <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)); }
/// <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); }