예제 #1
0
		/// <summary>
		/// Executes a method call over the DevTools protocol.
		/// </summary>
		/// <param name="webview">The WebView control.</param>
		/// <param name="method">The method name.</param>
		/// <param name="parameters">
		/// The JSON string with method parameters. May be null.
		/// See the <see href="https://chromedevtools.github.io/devtools-protocol/">
		/// DevTools Protocol documentation</see> for details of supported methods
		/// and the expected parameters.
		/// </param>
		/// <param name="cancellationToken">The token to monitor for cancellation requests.</param>
		/// <returns>
		/// The JSON string with the response. Structure of the response varies depending
		/// on the method name and is defined by the &apos;RETURN OBJECT&apos; section of
		/// the Chrome DevTools Protocol command description.
		/// </returns>
		/// <remarks>
		/// Usage of the ExecuteDevToolsMethodAsync function does not require an active
		/// DevTools front-end or remote-debugging session. Other active DevTools sessions
		/// will continue to function independently. However, any modification of global
		/// browser state by one session may not be reflected in the UI of other sessions.
		/// <para/>
		/// Communication with the DevTools front-end (when displayed) can be logged
		/// for development purposes by passing the `--devtools-protocol-log-
		/// file=&lt;path&gt;` command-line flag.
		/// </remarks>
		public static Task<string> ExecuteDevToolsMethodAsync(this IChromiumWebView webview, string method, string parameters, CancellationToken cancellationToken)
		{
			CefValue args = null;
			if (parameters != null)
			{
				args = CefApi.CefParseJSON(parameters, CefJsonParserOptions.AllowTrailingCommas, out string errorMessage);
				if (args is null)
					throw new ArgumentOutOfRangeException(nameof(parameters), errorMessage is null ? "An error occurred during JSON parsing." : errorMessage);
			}
			return ExecuteDevToolsMethodAsync(webview, method, args is null ? default(CefDictionaryValue) : args.GetDictionary(), cancellationToken);
		}
예제 #2
0
		private static async Task<string> ExecuteDevToolsMethodInternalAsync(IChromiumWebView webview, string method, CefDictionaryValue parameters, CancellationToken cancellationToken)
		{
			CefBrowser browser = webview.BrowserObject;
			if (browser is null)
				throw new InvalidOperationException();

			cancellationToken.ThrowIfCancellationRequested();

			CefBrowserHost browserHost = browser.Host;
			DevToolsProtocolClient protocolClient = GetProtocolClient(browserHost);

			await CefNetSynchronizationContextAwaiter.GetForThread(CefThreadId.UI);
			cancellationToken.ThrowIfCancellationRequested();

			int messageId = browserHost.ExecuteDevToolsMethod(protocolClient.IncrementMessageId(), method, parameters);
			protocolClient.UpdateLastMessageId(messageId);
			DevToolsMethodResult r;
			if (cancellationToken.CanBeCanceled)
			{
				Task<DevToolsMethodResult> waitTask = protocolClient.WaitForMessageAsync(messageId, DevToolsCallCompletionSource.ConvertUtf8BufferToJsonString);
				await Task.WhenAny(waitTask, Task.Delay(Timeout.Infinite, cancellationToken)).ConfigureAwait(false);
				cancellationToken.ThrowIfCancellationRequested();
				r = waitTask.Result;
			}
			else
			{
				r = await protocolClient.WaitForMessageAsync(messageId, DevToolsCallCompletionSource.ConvertUtf8BufferToJsonString).ConfigureAwait(false);
			}
			if (r.Success)
			{
				if (r.Result is byte[] buff)
					return Encoding.UTF8.GetString(buff);
				return r.Result as string;
			}

			CefValue errorValue;
			if (r.Result is byte[] buffer)
				errorValue = CefApi.CefParseJSONBuffer(buffer, CefJsonParserOptions.AllowTrailingCommas);
			else
				errorValue = CefApi.CefParseJSON(r.Result as string, CefJsonParserOptions.AllowTrailingCommas);
			if (errorValue is null)
				throw new DevToolsProtocolException($"An unknown error occurred while trying to execute the '{method}' method.");
			throw new DevToolsProtocolException(errorValue.GetDictionary().GetString("message"));
		}