// Copyright © 2020 The CefSharp Authors. All rights reserved. // // Use of this source code is governed by a BSD-style license that can be found in the LICENSE file. using System.Collections.Generic; using System.Threading.Tasks; using CefSharp.DevTools; using CefSharp.Internals; using CefSharp.Web; namespace CefSharp { /// /// Extensions for accessing DevTools through /// public static class DevToolsExtensions { /// /// Execute a method call over the DevTools protocol. This is a more structured /// version of SendDevToolsMessage. /// See the DevTools protocol documentation at https://chromedevtools.github.io/devtools-protocol/ for details /// of supported methods and the expected JSON message format. /// See the SendDevToolsMessage documentation for additional usage information. /// /// browser host /// is an incremental number that uniquely identifies the message (pass 0 to have the next number assigned /// automatically based on previous values) /// is the method name /// are the method parameters represented as a , /// which may be empty. /// return the assigned message Id if called on the CEF UI thread and the message was /// successfully submitted for validation, otherwise 0 public static int ExecuteDevToolsMethod(this IBrowserHost browserHost, int messageId, string method, JsonString parameters) { WebBrowserExtensions.ThrowExceptionIfBrowserHostNull(browserHost); var json = parameters == null ? null : parameters.Json; return browserHost.ExecuteDevToolsMethod(messageId, method, json); } /// /// Execute a method call over the DevTools protocol. This is a more structured /// version of SendDevToolsMessage. 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 dictionary contents. /// See the SendDevToolsMessage documentation for additional usage information. /// /// the browser instance /// is an incremental number that uniquely identifies the message (pass 0 to have the next number assigned /// automatically based on previous values) /// is the method name /// are the method parameters represented as a dictionary, /// which may be empty. /// 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. public static Task ExecuteDevToolsMethodAsync(this IBrowser browser, int messageId, string method, IDictionary 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); } /// /// Execute a method call over the DevTools protocol. This is a more structured /// version of SendDevToolsMessage. 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 dictionary contents. /// See the SendDevToolsMessage documentation for additional usage information. /// /// the ChromiumWebBrowser instance /// is an incremental number that uniquely identifies the message (pass 0 to have the next number assigned /// automatically based on previous values) /// is the method name /// are the method parameters represented as a dictionary, /// which may be empty. /// 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. public static Task ExecuteDevToolsMethodAsync(this IChromiumWebBrowserBase chromiumWebBrowser, int messageId, string method, IDictionary parameters = null) { var browser = chromiumWebBrowser.BrowserCore; return browser.ExecuteDevToolsMethodAsync(messageId, method, parameters); } /// /// Gets a new Instance of the DevTools client for the chromiumWebBrowser /// instance. /// /// the chromiumWebBrowser instance /// DevToolsClient public static DevToolsClient GetDevToolsClient(this IChromiumWebBrowserBase chromiumWebBrowser) { var browser = chromiumWebBrowser.BrowserCore; return browser.GetDevToolsClient(); } /// /// Gets a new Instance of the DevTools client /// /// the IBrowser instance /// DevToolsClient public static DevToolsClient GetDevToolsClient(this IBrowser browser) { WebBrowserExtensions.ThrowExceptionIfBrowserNull(browser); var browserHost = browser.GetHost(); WebBrowserExtensions.ThrowExceptionIfBrowserHostNull(browserHost); var devToolsClient = new DevToolsClient(browser); var observerRegistration = browserHost.AddDevToolsMessageObserver(devToolsClient); devToolsClient.SetDevToolsObserverRegistration(observerRegistration); return devToolsClient; } /// /// Set the Document Content for the Main Frame using DevTools Protocol. /// /// ChromiumWebBrowser instance /// html /// Task that can be awaited to determine if the content was successfully updated. public static Task SetMainFrameDocumentContentAsync(this IChromiumWebBrowserBase chromiumWebBrowser, string html) { var browser = chromiumWebBrowser.BrowserCore; return browser.SetMainFrameDocumentContentAsync(html); } /// /// Set the Document Content for the Main Frame using DevTools Protocol. /// /// the browser instance /// html /// Task that can be awaited to determine if the content was successfully updated. public static async Task SetMainFrameDocumentContentAsync(this IBrowser browser, string html) { WebBrowserExtensions.ThrowExceptionIfBrowserNull(browser); using (var client = browser.GetDevToolsClient()) { var response = await client.Page.GetFrameTreeAsync().ConfigureAwait(false); var frames = response.FrameTree; var mainFrame = frames.Frame; var setContentResponse = await client.Page.SetDocumentContentAsync(mainFrame.Id, html).ConfigureAwait(false); return setContentResponse.Success; } } } }