/// <summary> /// This method scrolls element into view if needed, and then uses <seealso cref="Page.ScreenshotDataAsync(ScreenshotOptions)"/> to take a screenshot of the element. /// If the element is detached from DOM, the method throws an error. /// </summary> /// <returns>The task</returns> /// <param name="file">The file path to save the image to. The screenshot type will be inferred from file extension. /// If path is a relative path, then it is resolved relative to current working directory. If no path is provided, /// the image won't be saved to the disk.</param> /// <param name="options">Screenshot options.</param> public async Task ScreenshotAsync(string file, ScreenshotOptions options) { if (!options.Type.HasValue) { options.Type = ScreenshotOptions.GetScreenshotTypeFromFile(file); } var data = await ScreenshotDataAsync(options).ConfigureAwait(false); using (var fs = AsyncFileHelper.CreateStream(file, FileMode.Create)) { await fs.WriteAsync(data, 0, data.Length).ConfigureAwait(false); } }
internal static async Task <string> ReadProtocolStreamStringAsync(ChromiumSession client, string handle, string path) { var result = new StringBuilder(); var fs = !string.IsNullOrEmpty(path) ? AsyncFileHelper.CreateStream(path, FileMode.Create) : null; try { bool eof = false; while (!eof) { var response = await client.SendAsync(new IOReadRequest { Handle = handle, }).ConfigureAwait(false); eof = response.Eof.Value; result.Append(response.Data); if (fs != null) { var data = Encoding.UTF8.GetBytes(response.Data); await fs.WriteAsync(data, 0, data.Length).ConfigureAwait(false); } } await client.SendAsync(new IOCloseRequest { Handle = handle, }).ConfigureAwait(false); return(result.ToString()); } finally { fs?.Dispose(); } }
internal static async Task <byte[]> ReadProtocolStreamByteAsync(ChromiumSession client, string handle, string path) { IEnumerable <byte> result = null; bool eof = false; var fs = !string.IsNullOrEmpty(path) ? AsyncFileHelper.CreateStream(path, FileMode.Create) : null; try { while (!eof) { var response = await client.SendAsync(new IOReadRequest { Handle = handle, }).ConfigureAwait(false); eof = response.Eof.Value; var data = Convert.FromBase64String(response.Data); result = result == null ? data : result.Concat(data); if (fs != null) { await fs.WriteAsync(data, 0, data.Length).ConfigureAwait(false); } } await client.SendAsync(new IOCloseRequest { Handle = handle, }).ConfigureAwait(false); return(result.ToArray()); } finally { fs?.Dispose(); } }
internal async Task <ElementHandle> AddStyleTagAsync(AddTagOptions options) { const string addStyleUrl = @"async function addStyleUrl(url) { const link = document.createElement('link'); link.rel = 'stylesheet'; link.href = url; const promise = new Promise((res, rej) => { link.onload = res; link.onerror = rej; }); document.head.appendChild(link); await promise; return link; }"; const string addStyleContent = @"async function addStyleContent(content) { const style = document.createElement('style'); style.type = 'text/css'; style.appendChild(document.createTextNode(content)); const promise = new Promise((res, rej) => { style.onload = res; style.onerror = rej; }); document.head.appendChild(style); await promise; return style; }"; if (!string.IsNullOrEmpty(options.Url)) { var url = options.Url; try { var context = await GetExecutionContextAsync().ConfigureAwait(false); return((await context.EvaluateFunctionHandleAsync(addStyleUrl, url).ConfigureAwait(false)) as ElementHandle); } catch (PuppeteerException) { throw new PuppeteerException($"Loading style from {url} failed"); } } if (!string.IsNullOrEmpty(options.Path)) { var contents = await AsyncFileHelper.ReadAllText(options.Path).ConfigureAwait(false); contents += "//# sourceURL=" + options.Path.Replace("\n", string.Empty); var context = await GetExecutionContextAsync().ConfigureAwait(false); return((await context.EvaluateFunctionHandleAsync(addStyleContent, contents).ConfigureAwait(false)) as ElementHandle); } if (!string.IsNullOrEmpty(options.Content)) { var context = await GetExecutionContextAsync().ConfigureAwait(false); return((await context.EvaluateFunctionHandleAsync(addStyleContent, options.Content).ConfigureAwait(false)) as ElementHandle); } throw new ArgumentException("Provide options with a `Url`, `Path` or `Content` property"); }
internal async Task <ElementHandle> AddScriptTagAsync(AddTagOptions options) { const string addScriptUrl = @"async function addScriptUrl(url, type) { const script = document.createElement('script'); script.src = url; if(type) script.type = type; const promise = new Promise((res, rej) => { script.onload = res; script.onerror = rej; }); document.head.appendChild(script); await promise; return script; }"; const string addScriptContent = @"function addScriptContent(content, type = 'text/javascript') { const script = document.createElement('script'); script.type = type; script.text = content; let error = null; script.onerror = e => error = e; document.head.appendChild(script); if (error) throw error; return script; }"; async Task <ElementHandle> AddScriptTagPrivate(string script, string urlOrContent, string type) { var context = await GetExecutionContextAsync().ConfigureAwait(false); return((string.IsNullOrEmpty(type) ? await context.EvaluateFunctionHandleAsync(script, urlOrContent).ConfigureAwait(false) : await context.EvaluateFunctionHandleAsync(script, urlOrContent, type).ConfigureAwait(false)) as ElementHandle); } if (!string.IsNullOrEmpty(options.Url)) { var url = options.Url; try { return(await AddScriptTagPrivate(addScriptUrl, url, options.Type).ConfigureAwait(false)); } catch (PuppeteerException) { throw new PuppeteerException($"Loading script from {url} failed"); } } if (!string.IsNullOrEmpty(options.Path)) { var contents = await AsyncFileHelper.ReadAllText(options.Path).ConfigureAwait(false); contents += "//# sourceURL=" + options.Path.Replace("\n", string.Empty); return(await AddScriptTagPrivate(addScriptContent, contents, options.Type).ConfigureAwait(false)); } if (!string.IsNullOrEmpty(options.Content)) { return(await AddScriptTagPrivate(addScriptContent, options.Content, options.Type).ConfigureAwait(false)); } throw new ArgumentException("Provide options with a `Url`, `Path` or `Content` property"); }