Пример #1
0
        private void OpenPopup_Click(object sender, RoutedEventArgs e)
        {
            var tab = tabs.SelectedItem as WebViewTab;

            if (tab == null)
            {
                return;
            }

            IChromiumWebView webView = tab.WebView;

            if (webView == null)
            {
                return;
            }

            tab.PopupHandlingDisabled = true;
            EventHandler <CreateWindowEventArgs> callback = null;

            callback = (a, b) => {
                tab.PopupHandlingDisabled = false;
                Dispatcher.UIThread.Post(() => webView.CreateWindow -= callback, DispatcherPriority.Normal);
            };
            webView.CreateWindow += callback;
            webView.GetMainFrame().ExecuteJavaScript("window.open('http://example.com')", null, 1);
        }
Пример #2
0
		/// <summary>
		/// Clears browser cookies.
		/// </summary>
		/// <param name="webview">The WebView control.</param>
		/// <param name="cancellationToken">The token to monitor for cancellation requests.</param>
		/// <returns>The task object representing the asynchronous operation.</returns>
		public static async Task ClearBrowserCookiesAsync(this IChromiumWebView webview, CancellationToken cancellationToken)
		{
			if (webview is null)
				throw new ArgumentNullException(nameof(webview));

			ThrowIfNotEmptyResponse(await ExecuteDevToolsMethodInternalAsync(webview, "Network.clearBrowserCookies", null, cancellationToken).ConfigureAwait(false));
		}
Пример #3
0
		/// <summary>
		/// Captures page screenshot.
		/// </summary>
		/// <param name="webview">The WebView control.</param>
		/// <param name="settings">The capture settings or null.</param>
		/// <param name="targetStream">A stream to save the captured image to.</param>
		/// <param name="cancellationToken">The token to monitor for cancellation requests.</param>
		/// <returns>The task object representing the asynchronous operation.</returns>
		/// <exception cref="ArgumentNullException">
		/// <paramref name="webview"/> or <paramref name="targetStream"/> is null.
		/// </exception>
		/// <exception cref="DevToolsProtocolException">
		/// An error occurred while trying to execute a DevTools Protocol method.
		/// </exception>
		/// <exception cref="InvalidOperationException">Other error occurred.</exception>
		public static async Task CaptureScreenshotAsync(this IChromiumWebView webview, PageCaptureSettings settings, Stream targetStream, CancellationToken cancellationToken)
		{
			if (webview is null)
				throw new ArgumentNullException(nameof(webview));

			if (targetStream is null)
				throw new ArgumentNullException(nameof(targetStream));

			CefDictionaryValue args;
			if (settings is null)
			{
				args = null;
			}
			else
			{
				args = new CefDictionaryValue();
				if (settings.Format == ImageCompressionFormat.Jpeg)
				{
					args.SetString("format", "jpeg");
					if (settings.Quality.HasValue)
						args.SetInt("quality", settings.Quality.Value);
				}
				if (!settings.FromSurface)
					args.SetBool("fromSurface", false);
				if (settings.Viewport != null)
				{
					PageViewport viewport = settings.Viewport;
					var viewportDict = new CefDictionaryValue();
					viewportDict.SetDouble("x", viewport.X);
					viewportDict.SetDouble("y", viewport.Y);
					viewportDict.SetDouble("width", viewport.Width);
					viewportDict.SetDouble("height", viewport.Height);
					viewportDict.SetDouble("scale", viewport.Scale);
					args.SetDictionary("clip", viewportDict);
				}
				if (settings.CaptureBeyondViewport)
					args.SetBool("captureBeyondViewport", true);
			}

			byte[] rv = (byte[])await ExecuteDevToolsMethodInternalAsync(webview, "Page.captureScreenshot", args, null, cancellationToken).ConfigureAwait(false);

			if (rv != null && rv.Length > 11 && rv[rv.Length - 1] == '}' && rv[rv.Length - 2] == '"'
				&& "{\"data\":\"".Equals(Encoding.ASCII.GetString(rv, 0, 9), StringComparison.Ordinal))
			{
				using (var input = new MemoryStream(rv, 9, rv.Length - 11))
				using (var base64Transform = new FromBase64Transform(FromBase64TransformMode.IgnoreWhiteSpaces))
				using (var cryptoStream = new CryptoStream(input, base64Transform, CryptoStreamMode.Read))
				{
					await cryptoStream.CopyToAsync(targetStream, 4096, cancellationToken).ConfigureAwait(false);
					await targetStream.FlushAsync(cancellationToken).ConfigureAwait(false);
				}
			}
			else
			{
				throw new InvalidOperationException();
			}
		}
Пример #4
0
        private void TestV8ValueTypes_Click(object sender, RoutedEventArgs e)
        {
            IChromiumWebView webView = SelectedView;

            if (webView == null)
            {
                return;
            }

            webView.GetMainFrame().SendProcessMessage(CefProcessId.Renderer, new CefProcessMessage("TestV8ValueTypes"));
        }
Пример #5
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);
		}
Пример #6
0
        private async void Alert_Click(object sender, RoutedEventArgs e)
        {
            IChromiumWebView webView = SelectedView;

            if (webView == null)
            {
                return;
            }

            dynamic scriptableObject = await webView.GetMainFrame().GetScriptableObjectAsync(CancellationToken.None).ConfigureAwait(false);

            scriptableObject.window.alert("hello");
        }
Пример #7
0
		/// <summary>
		/// Overrides user agent with the given string.
		/// </summary>
		/// <param name="webview">The WebView control.</param>
		/// <param name="userAgent">User agent to use.</param>
		/// <param name="acceptLanguage">Browser langugage to emulate.</param>
		/// <param name="platform">The platform navigator.platform should return.</param>
		/// <param name="cancellationToken">The token to monitor for cancellation requests.</param>
		/// <returns>The task object representing the asynchronous operation.</returns>
		public static async Task SetUserAgentOverrideAsync(this IChromiumWebView webview, string userAgent, string acceptLanguage, string platform, CancellationToken cancellationToken)
		{
			if (webview is null)
				throw new ArgumentNullException(nameof(webview));

			var args = new CefDictionaryValue();
			args.SetString("userAgent", userAgent);
			if (acceptLanguage is not null)
				args.SetString("acceptLanguage", acceptLanguage);
			if (platform is not null)
				args.SetString("platform", platform);
			ThrowIfNotEmptyResponse(await ExecuteDevToolsMethodInternalAsync(webview, "Emulation.setUserAgentOverride", args, cancellationToken).ConfigureAwait(false));
		}
Пример #8
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 dictionaly 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, CefDictionaryValue parameters, CancellationToken cancellationToken)
		{
			if (webview is null)
				throw new ArgumentNullException(nameof(webview));

			if (method is null)
				throw new ArgumentNullException(nameof(method));

			method = method.Trim();
			if (method.Length == 0)
				throw new ArgumentOutOfRangeException(nameof(method));

			return ExecuteDevToolsMethodInternalAsync(webview, method, parameters, cancellationToken);
		}
Пример #9
0
        /// <summary>
        /// Clears browser cookies.
        /// </summary>
        /// <param name="webview">The WebView control.</param>
        /// <param name="cancellationToken">The token to monitor for cancellation requests.</param>
        /// <returns>The task object representing the asynchronous operation.</returns>
        public static async Task ClearBrowserCookiesAsync(this IChromiumWebView webview, CancellationToken cancellationToken)
        {
            if (webview is null)
            {
                throw new ArgumentNullException(nameof(webview));
            }

            byte[] rv = await ExecuteDevToolsMethodInternalAsync(webview, "Network.clearBrowserCookies", null, cancellationToken);

            if (rv is null || rv.Length != 2 || rv[0] != '{' || rv[1] != '}')
            {
                throw new InvalidOperationException();
            }
        }
Пример #10
0
		/// <summary>
		/// Enables touch on platforms which do not support them.
		/// </summary>
		/// <param name="webview">The WebView control.</param>
		/// <param name="enabled">True whether the touch event emulation should be enabled.</param>
		/// <param name="maxTouchPoints">Maximum touch points supported. Defaults to one.</param>
		/// <param name="cancellationToken">The token to monitor for cancellation requests.</param>
		/// <returns>The task object representing the asynchronous operation.</returns>
		public static async Task SetTouchEmulationEnabledAsync(this IChromiumWebView webview, bool enabled, int? maxTouchPoints, CancellationToken cancellationToken)
		{
			if (webview is null)
				throw new ArgumentNullException(nameof(webview));

			var args = new CefDictionaryValue();
			args.SetBool("enabled", enabled);
			if (maxTouchPoints is not null)
			{
				if (maxTouchPoints.Value < 1 || maxTouchPoints.Value > 16)
					throw new ArgumentOutOfRangeException(nameof(maxTouchPoints), "Touch points must be between 1 and 16.");
				args.SetInt("maxTouchPoints", maxTouchPoints.Value);
			}
			ThrowIfNotEmptyResponse(await ExecuteDevToolsMethodInternalAsync(webview, "Emulation.setTouchEmulationEnabled", args, cancellationToken).ConfigureAwait(false));
		}
Пример #11
0
        private static async Task <byte[]> 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);
                await Task.WhenAny(waitTask, Task.Delay(Timeout.Infinite, cancellationToken)).ConfigureAwait(false);

                cancellationToken.ThrowIfCancellationRequested();
                r = waitTask.Result;
            }
            else
            {
                r = await protocolClient.WaitForMessageAsync(messageId).ConfigureAwait(false);
            }
            if (r.Success)
            {
                return(r.Result);
            }

            CefValue errorValue = CefApi.CefParseJSONBuffer(r.Result, 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"));
        }
Пример #12
0
		/// <summary>
		/// Executes a method call over the DevTools protocol.
		/// </summary>
		/// <typeparam name="T">The type of object to return.</typeparam>
		/// <param name="webview">The WebView control.</param>
		/// <param name="method">The method name.</param>
		/// <param name="parameters">
		/// The dictionaly 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="convert">
		/// A callback function that converts the result content into an object of type <see cref="T"/>.
		/// If null, a byte array containing a UTF-8-encoded copy of the content is returned.
		/// </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 async Task<T> ExecuteDevToolsMethodAsync<T>(this IChromiumWebView webview, string method, CefDictionaryValue parameters, ConvertUtf8BufferToTypeDelegate<T> convert, CancellationToken cancellationToken)
			where T : class
		{
			if (webview is null)
				throw new ArgumentNullException(nameof(webview));

			if (method is null)
				throw new ArgumentNullException(nameof(method));

			method = method.Trim();
			if (method.Length == 0)
				throw new ArgumentOutOfRangeException(nameof(method));

			object result = await ExecuteDevToolsMethodInternalAsync(webview, method, parameters, (buffer, size) => convert(buffer, size), cancellationToken).ConfigureAwait(false);
			return (T)result;
		}
Пример #13
0
		/// <summary>
		/// Emulates the given media type or media feature for CSS media queries.
		/// </summary>
		/// <param name="webview">The WebView control.</param>
		/// <param name="media">Media type to emulate. Empty string disables the override.</param>
		/// <param name="features">Media features to emulate.</param>
		/// <param name="cancellationToken">The token to monitor for cancellation requests.</param>
		/// <returns>The task object representing the asynchronous operation.</returns>
		public static async Task SetEmulatedMediaAsync(this IChromiumWebView webview, string media, IDictionary<string, string> features, CancellationToken cancellationToken)
		{
			if (webview is null)
				throw new ArgumentNullException(nameof(webview));

			var args = new CefDictionaryValue();
			args.SetString("media", media);
			if (features is not null)
			{
				foreach (KeyValuePair<string, string> feature in features)
				{
					if (string.IsNullOrWhiteSpace(feature.Key))
						throw new ArgumentOutOfRangeException(nameof(features), "Key may not be empty.");
					args.SetString(feature.Key, feature.Value);
				}
			}
			ThrowIfNotEmptyResponse(await ExecuteDevToolsMethodInternalAsync(webview, "Emulation.setEmulatedMedia", args, cancellationToken).ConfigureAwait(false));
		}
Пример #14
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 dictionaly 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 async Task <string> ExecuteDevToolsMethodAsync(this IChromiumWebView webview, string method, CefDictionaryValue parameters, CancellationToken cancellationToken)
        {
            if (webview is null)
            {
                throw new ArgumentNullException(nameof(webview));
            }

            if (method is null)
            {
                throw new ArgumentNullException(nameof(method));
            }

            method = method.Trim();
            if (method.Length == 0)
            {
                throw new ArgumentOutOfRangeException(nameof(method));
            }

            byte[] rv = await ExecuteDevToolsMethodInternalAsync(webview, method, parameters, cancellationToken).ConfigureAwait(false);

            return(rv is null ? null : Encoding.UTF8.GetString(rv));
        }
Пример #15
0
 /// <summary>
 /// Executes a method call over the DevTools protocol without any optional parameters.
 /// </summary>
 /// <param name="webview">The WebView control.</param>
 /// <param name="method">The method name.</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, CancellationToken cancellationToken)
 {
     return(ExecuteDevToolsMethodAsync(webview, method, default(CefDictionaryValue), cancellationToken));
 }
Пример #16
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>
 /// <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)
 {
     return(ExecuteDevToolsMethodAsync(webview, method, parameters, CancellationToken.None));
 }