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