diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml
index 3af0beb6c..8ff4bca75 100644
--- a/.github/FUNDING.yml
+++ b/.github/FUNDING.yml
@@ -1,12 +1,3 @@
# These are supported funding model platforms
-github: hardkoded
-patreon: # Replace with a single Patreon username
-open_collective: hardkoded-projects
-ko_fi: # Replace with a single Ko-fi username
-tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
-community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
-liberapay: # Replace with a single Liberapay username
-issuehunt: # Replace with a single IssueHunt username
-otechie: # Replace with a single Otechie username
-custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2']
+github: amaitland
\ No newline at end of file
diff --git a/.github/workflows/on-push-do-docs.yml b/.github/workflows/on-push-do-docs.yml
deleted file mode 100644
index 84eb62b4c..000000000
--- a/.github/workflows/on-push-do-docs.yml
+++ /dev/null
@@ -1,22 +0,0 @@
-name: on-push-do-docs
-on:
- push:
-jobs:
- docs:
- runs-on: windows-latest
- steps:
- - uses: actions/checkout@v2
- - name: Run MarkdownSnippets
- run: |
- dotnet tool install --global MarkdownSnippets.Tool
- mdsnippets ${GITHUB_WORKSPACE}
- shell: bash
- - name: Push changes
- run: |
- git config --local user.email "action@github.com"
- git config --local user.name "GitHub Action"
- git commit -m "Docs changes" -a || echo "nothing to commit"
- remote="https://${GITHUB_ACTOR}:${{secrets.GITHUB_TOKEN}}@github.com/${GITHUB_REPOSITORY}.git"
- branch="${GITHUB_REF:11}"
- git push "${remote}" ${branch} || echo "nothing to push"
- shell: bash
\ No newline at end of file
diff --git a/.gitignore b/.gitignore
index 015a8f464..8159459a2 100644
--- a/.gitignore
+++ b/.gitignore
@@ -299,3 +299,4 @@ samples/PupppeterSharpAspNetFrameworkSample/PupppeterSharpAspNetFrameworkSample/
# Visual Studio Code user config directory
.vscode/
+/lib/PuppeteerSharp.Tests/Screenshots/golden-chromium/test.png
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index b3fdcca1c..acc27fd64 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -1,11 +1,9 @@
# How to Contribute
-If you are interested in contributing to Puppeteer Sharp, Thank you!
+If you are interested in contributing to CefSharp.Dom, Thank you!
-Coding is not for lonely wolves. Welcome to the pack!
-
-The project has a clear roadmap we want to follow. If you want to contribute, ask before submitting a PR. We will analyze if it’s the right moment to implement that feature or not.
-If you don’t know what to do, ASK! We have many many things to implement :)
+If you want to contribute, ask before submitting a PR.
+If you don’t know what to do, ASK!
## Getting setup
@@ -20,13 +18,10 @@ You can run this PowerShell script on Windows
```
New-SelfSignedCertificate -Subject "localhost" -FriendlyName "Puppeteer" -CertStoreLocation "cert:\CurrentUser\My"
-Get-ChildItem -Path cert:\CurrentUSer\my | where { $_.friendlyname -eq "Puppeteer" } | Export-Certificate -FilePath C:\projects\puppeteer-sharp\lib\PuppeteerSharp.TestServer\testCert.cer
+Get-ChildItem -Path cert:\CurrentUSer\my | where { $_.friendlyname -eq "Puppeteer" } | Export-Certificate -FilePath C:\Projects\CefSharp.Dom\lib\PuppeteerSharp.TestServer\testCert.cer
```
-On MacOS, you can create an “SSL Server” certificate using the Keychain Access app and then export it to `.\lib\PuppeteerSharp.TestServer\testCert.cer`
-
-
## Code reviews
All submissions, including submissions by project members, require review. We
diff --git a/ISSUE_TEMPLATE.md b/ISSUE_TEMPLATE.md
index dcc9826b6..e63a827b5 100644
--- a/ISSUE_TEMPLATE.md
+++ b/ISSUE_TEMPLATE.md
@@ -1,11 +1,11 @@
-## Looking for some help? Get priority support by [sponsoring the project](https://github.com/sponsors/hardkoded)/
+## Looking for some help? Get priority support by [sponsoring the project](https://github.com/sponsors/amaitland)/
**Before you file a bug, have you:**
-* Tried upgrading to newest version of PuppeteerSharp, to see if your issue has already been resolved and released?
-* Checked existing open *and* closed [issues](https://github.com/kblok/puppeteer-sharp/issues?utf8=%E2%9C%93&q=is%3Aissue), to see if the issue has already been reported?
+* Tried upgrading to newest version of CefSharp.Dom, to see if your issue has already been resolved and released?
+* Checked existing open *and* closed issues, to see if the issue has already been reported?
* Tried reproducing your problem in a new isolated project?
-* Considered if this is a general question and not a bug?. For general questions please use [StackOverflow](https://stackoverflow.com/search?q=puppeteer-sharp).
+* Considered if this is a general question and not a bug?. For general questions please use Discussions.
### Description
@@ -20,10 +20,7 @@ E.g.
```csharp
// Arrange
-var options = new LaunchOptions { /* */ };
-var chromiumRevision = BrowserFetcher.DefaultRevision;
-var browser = await Puppeteer.LaunchAsync(options, chromiumRevision);
-var page = browser.NewPageAsync();
+var devtoolsContext = await chromiumWebBrowser.CreateDevToolsContextAsync();
// Act
...
@@ -42,12 +39,12 @@ var page = browser.NewPageAsync();
### Versions
-* Which version of PuppeteerSharp are you using?
-* Which .NET runtime and version are you targeting? E.g. .NET framework 4.6.1 or .NET Core 2.0.
+* Which version of CefSharp.Dom are you using?
+* Which .NET runtime and version are you targeting? E.g. .NET framework 4.6.1 or .NET Core 3.1.
### Additional Information
Any additional information, configuration or data that might be necessary to reproduce the issue.
-
+
diff --git a/LICENSE b/LICENSE
index 977830f89..ec2fe73b5 100644
--- a/LICENSE
+++ b/LICENSE
@@ -1,6 +1,7 @@
MIT License
Copyright (c) 2017 Darío Kondratiuk
+Copyright (c) 2021 Alex Maitland
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
diff --git a/README.md b/README.md
index a37841bb1..44e0bcaf7 100644
--- a/README.md
+++ b/README.md
@@ -1,110 +1,184 @@
-# Puppeteer Sharp
+# CefSharp.Dom (Formerly CefSharp.Puppeteer)
-[![NuGet](https://buildstats.info/nuget/PuppeteerSharp)][NugetUrl]
-[![Build status](https://ci.appveyor.com/api/projects/status/pwfkjb0c4jfdo7lc/branch/master?svg=true&pendingText=master&failingText=master&passingText=master)][BuildUrl]
-[![Demo build status](https://ci.appveyor.com/api/projects/status/10g64a4aa0083wgf/branch/master?svg=true&pendingText=demo&failingText=demo&passingText=demo)][BuildDemoUrl]
-[![CodeFactor](https://www.codefactor.io/repository/github/hardkoded/puppeteer-sharp/badge)][CodeFactorUrl]
-[![Backers](https://opencollective.com/hardkoded-projects/backers/badge.svg)][Backers]
-[![xs:code](https://img.shields.io/static/v1?logo=data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMzAiIGhlaWdodD0iNDUiIHZpZXdCb3g9IjAgMCAzMCA0NSIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZD0iTTIwLjgzMjEgMzcuNDg4OVYyOS40NzJDMjAuODMyMSAyNi43NjQ1IDE5LjI5NjggMjQuNjY5MiAxNi44NTMxIDI0Ljk1NDJWMjAuMTgzMUMxOS4yOTY4IDIwLjQ2MjggMjAuODMyMSAxOC4zNTcgMjAuODMyMSAxNS42NDQyVjcuNjI3MjhDMjAuODMyMSAwLjI5MTE2NiAyNS4xMjQ2IDAuODEzNjY1IDI5LjM3NDYgMC44MTM2NjVWNC44MDM2NkMyNi45MzA5IDQuNTIzOTQgMjUuMzk1NiA0LjkxNDUgMjUuMzk1NiA3LjYyNzI4VjE1LjY0NDJDMjUuMzk1NiAxOC43NDc2IDI0LjQyODcgMjEuMTE3MyAyMi4zODM0IDIyLjUzMTdDMjQuNDI4NyAyMy45OTg5IDI1LjM5NTYgMjYuMzY4NyAyNS4zOTU2IDI5LjQ3MlYzNy40ODg5QzI1LjM5NTYgNDAuMTk2NCAyNi45MzA5IDQwLjU5MjMgMjkuMzc0NiA0MC4zMTI2VjQ0LjYwMzRDMjUuNjkzMSA0NC41OTgxIDIwLjgzMjEgNDQuODI1MSAyMC44MzIxIDM3LjQ4ODlaIiBmaWxsPSJ3aGl0ZSIvPgo8cGF0aCBkPSJNMC41MDY0MDkgNDQuNTk4MVY0MC4zMDczQzIuOTUwMTYgNDAuNTg3IDQuNDg1NDcgNDAuMTk2NCA0LjQ4NTQ3IDM3LjQ4MzZWMjkuNDcyQzQuNDg1NDcgMjYuMzY4NiA1LjQ1MjM1IDIzLjk5ODkgNy40OTc2NiAyMi41MzE3QzUuNDUyMzUgMjEuMTIyNSA0LjQ4NTQ3IDE4Ljc0NzUgNC40ODU0NyAxNS42NDQyVjcuNjI3MjVDNC40ODU0NyA0LjkxOTc1IDIuOTUwMTYgNC41MjM5MiAwLjUwNjQwOSA0LjgwMzY0VjAuODEzNjM4QzQuNzU2NDEgMC44MTM2MzggOS4wNDg5MSAwLjI4NTg2IDkuMDQ4OTEgNy42MjcyNVYxNS42NDQyQzkuMDQ4OTEgMTguMzUxNyAxMC41ODQyIDIwLjQ2MjggMTMuMDI4IDIwLjE4MzFWMjQuOTU0MkMxMC41ODQyIDI0LjY3NDUgOS4wNDg5MSAyNi43NjQ1IDkuMDQ4OTEgMjkuNDcyVjM3LjQ4ODlDOS4wNDg5MSA0NC44MjUgNC4xOTMyOCA0NC41OTgxIDAuNTA2NDA5IDQ0LjU5ODFaIiBmaWxsPSJ3aGl0ZSIvPgo8L3N2Zz4K&message=xs:code&label=Ping+me+on&color=%23007EFF)](https://xscode.com/profile/kblok)
+[![Nuget](https://img.shields.io/nuget/v/CefSharp.Dom?style=for-the-badge)](https://www.nuget.org/packages/CefSharp.Dom/)
+[![AppVeyor](https://img.shields.io/appveyor/build/cefsharp/cefsharp-dom?style=for-the-badge)](https://ci.appveyor.com/project/cefsharp/cefsharp-dom)
+[![AppVeyor tests](https://img.shields.io/appveyor/tests/cefsharp/cefsharp-dom?style=for-the-badge)](https://ci.appveyor.com/project/cefsharp/cefsharp-dom/build/tests)
+[![GitHub](https://img.shields.io/github/license/cefsharp/CefSharp.Dom?style=for-the-badge)](https://github.com/cefsharp/CefSharp.Dom/blob/main/LICENSE)
-[NugetUrl]: https://www.nuget.org/packages/PuppeteerSharp/
-[BuildUrl]: https://ci.appveyor.com/project/kblok/puppeteer-sharp/branch/master
-[BuildDemoUrl]: https://ci.appveyor.com/project/kblok/puppeteer-sharp-0c8w9/branch/master
-[CodeFactorUrl]: https://www.codefactor.io/repository/github/hardkoded/puppeteer-sharp
-[Backers]: https://opencollective.com/hardkoded-projects
+CefSharp.Dom is a fork of [puppeteer-sharp by Darío Kondratiuk](https://github.com/hardkoded/puppeteer-sharp) that has been adapted specifically for use with CefSharp.
+- Strongly typed async DOM API
+- Direct communication with the ChromiumWebBrowser instance rather than opening a web socket.
+- 1:1 mapping of DevToolsContext and ChromiumWebBrowser
+- CEF only supports a subset of features, features will be added/removed as the project matures
+# Prerequisites
-Puppeteer Sharp is a .NET port of the official [Node.JS Puppeteer API](https://github.com/puppeteer/puppeteer).
+ * .Net 4.7.2 or .Net Core 3.1 or greater
+ * CefSharp 104.4.180 or greater
-# Puppeteer-Sharp 3 is here!
+# Questions and Support
-Check out the [blog post](https://www.hardkoded.com/blog/puppeteer-sharp-3-is-here)!
+If you have an issue or a question:
-# Useful links
+* Ask a question on [Discussions](https://github.com/cefsharp/CefSharp.Dom/discussions).
-* [API Documentation](http://www.puppeteersharp.com/api/index.html)
-* Slack channel [#puppeteer-sharp](https://www.hardkoded.com/goto/pptr-slack)
-* [StackOverflow](https://stackoverflow.com/search?q=puppeteer-sharp)
-* [Issues](https://github.com/hardkoded/puppeteer-sharp/issues?utf8=%E2%9C%93&q=is%3Aissue)
+## Contributing Guide
-# Prerequisites
+See [this document](CONTRIBUTING.md) for information on how to contribute.
- * As Puppeteer-Sharp is a NetStandard 2.0 library, the minimum platform versions are .NET Framework 4.6.1 and .NET Core 2.0. [Read more](https://docs.microsoft.com/en-us/dotnet/standard/net-standard).
- * The minimum **Windows** versions supporting the WebSocket library are Windows 8 and Windows Server 2012. [Read more](https://docs.microsoft.com/en-us/dotnet/api/system.net.websockets?redirectedfrom=MSDN&view=netframework-4.7.2). If you need to run Puppeteer-Sharp on Windows 7 you can use [System.Net.WebSockets.Client.Managed](https://www.nuget.org/packages/System.Net.WebSockets.Client.Managed/) through the [LaunchOptions.WebSocketFactory](https://www.puppeteersharp.com/api/PuppeteerSharp.LaunchOptions.html#PuppeteerSharp_LaunchOptions_WebSocketFactory) property.
- * If you have issues running Chrome on Linux, the Puppeteer repo has a [great troubleshooting guide](https://github.com/puppeteer/puppeteer/blob/master/docs/troubleshooting.md).
- * X-server is required on Linux.
+# Usage
- # How to Contribute and Provide Feedback
+## DevToolsContext
-Some of the best ways to contribute are to try things out file bugs and fix issues.
+The **DevToolsContext** class is the main entry point into the library and can be created from a
+ChromiumWebBrowser instance.
+Only a **single** DevToolsContext should exist at any given time, when you are finished them make sure you
+dispose via DisposeAsync.
+Starting in version 2.x the **DevToolsContext** multiple calls to CreateDevToolsContextAsync will return the same
+instance per ChromiumWebBrowser and will be Disposed when the ChromiumWebBrowser is Disposed. If you need to use
+the DevToolsContext in multiple places in your code, calling CreateDevToolsContextAsync is now supported without dispoing.
+If the DevToolsContext is disposed then calls to CreateDevToolsContextAsync will create a new instance.
-If you have an issue or a question:
+```c#
+// Add using CefSharp.Dom; to get access to the
+// CreateDevToolsContextAsync extension method
+var devtoolsContext = await chromiumWebBrowser.CreateDevToolsContextAsync();
-* Ask a question on [Stack Overflow](https://stackoverflow.com/search?q=puppeteer-sharp).
-* File a [new issue](https://github.com/hardkoded/puppeteer-sharp/issues/new).
+// Manually dispose of context (prefer DisposeAsync as the whole API is async)
+await devToolsContext.DisposeAsync();
+```
-## Contributing Guide
+```c#
+// Dispose automatically via await using
+// https://docs.microsoft.com/en-us/dotnet/standard/garbage-collection/implementing-disposeasync#using-async-disposable
+await using var devtoolsContext = await chromiumWebBrowser.CreateDevToolsContextAsync();
+```
-See [this document](https://github.com/hardkoded/puppeteer-sharp/blob/master/CONTRIBUTING.md) for information on how to contribute.
+## DOM Access
-# Usage
+Read/write to the DOM
+
+
+```cs
+// Add using CefSharp.Dom to access CreateDevToolsContextAsync and related extension methods.
+await using var devToolsContext = await chromiumWebBrowser.CreateDevToolsContextAsync();
-## Take screenshots
+await devToolsContext.GoToAsync("http://www.google.com");
-
-
-```cs
-using var browserFetcher = new BrowserFetcher();
-await browserFetcher.DownloadAsync();
-await using var browser = await Puppeteer.LaunchAsync(
- new LaunchOptions { Headless = true });
-await using var page = await browser.NewPageAsync();
-await page.GoToAsync("http://www.google.com");
-await page.ScreenshotAsync(outputFile);
-```
-snippet source | anchor
-
+// Get element by Id
+// https://developer.mozilla.org/en-US/docs/Web/API/Document/querySelector
+var element = await devToolsContext.QuerySelectorAsync("#myElementId");
-You can also change the view port before generating the screenshot
+//Strongly typed element types (this is only a subset of the types mapped)
+var htmlDivElement = await devToolsContext.QuerySelectorAsync("#myDivElementId");
+var htmlSpanElement = await devToolsContext.QuerySelectorAsync("#mySpanElementId");
+var htmlSelectElement = await devToolsContext.QuerySelectorAsync("#mySelectElementId");
+var htmlInputElement = await devToolsContext.QuerySelectorAsync("#myInputElementId");
+var htmlFormElement = await devToolsContext.QuerySelectorAsync("#myFormElementId");
+var htmlAnchorElement = await devToolsContext.QuerySelectorAsync("#myAnchorElementId");
+var htmlImageElement = await devToolsContext.QuerySelectorAsync("#myImageElementId");
+var htmlTextAreaElement = await devToolsContext.QuerySelectorAsync("#myTextAreaElementId");
+var htmlButtonElement = await devToolsContext.QuerySelectorAsync("#myButtonElementId");
+var htmlParagraphElement = await devToolsContext.QuerySelectorAsync("#myParagraphElementId");
+var htmlTableElement = await devToolsContext.QuerySelectorAsync("#myTableElementId");
-
-
-```cs
-await Page.SetViewportAsync(new ViewPortOptions
+// Get a custom attribute value
+var customAttribute = await element.GetAttributeAsync("data-customAttribute");
+
+//Set innerText property for the element
+await element.SetInnerTextAsync("Welcome!");
+
+//Get innerText property for the element
+var innerText = await element.GetInnerTextAsync();
+
+//Get all child elements
+var childElements = await element.QuerySelectorAllAsync("div");
+
+//Change CSS style background colour
+await element.EvaluateFunctionAsync("e => e.style.backgroundColor = 'yellow'");
+
+//Type text in an input field
+await element.TypeAsync("Welcome to my Website!");
+
+//Click The element
+await element.ClickAsync();
+
+// Simple way of chaining method calls together when you don't need a handle to the HtmlElement
+var htmlButtonElementInnerText = await devToolsContext.QuerySelectorAsync("#myButtonElementId")
+ .AndThen(x => x.GetInnerTextAsync());
+
+//Event Handler
+//Expose a function to javascript, functions persist across navigations
+//So only need to do this once
+await devToolsContext.ExposeFunctionAsync("jsAlertButtonClick", () =>
{
- Width = 500,
- Height = 500
+ _ = devToolsContext.EvaluateExpressionAsync("window.alert('Hello! You invoked window.alert()');");
});
-```
-snippet source | anchor
-
+var jsAlertButton = await devToolsContext.QuerySelectorAsync("#jsAlertButton");
-## Generate PDF files
+//Write up the click event listner to call our exposed function
+_ = jsAlertButton.AddEventListenerAsync("click", "jsAlertButtonClick");
-
-
-```cs
-using var browserFetcher = new BrowserFetcher();
-await browserFetcher.DownloadAsync();
-await using var browser = await Puppeteer.LaunchAsync(new LaunchOptions {Headless = true});
-await using var page = await browser.NewPageAsync();
-await page.GoToAsync("http://www.google.com");
-await page.PdfAsync(outputFile);
+//Get a collection of HtmlElements
+var divElements = await devToolsContext.QuerySelectorAllAsync("div");
+
+foreach (var div in divElements)
+{
+ // Get a reference to the CSSStyleDeclaration
+ var style = await div.GetStyleAsync();
+
+ //Set the border to 1px solid red
+ await style.SetPropertyAsync("border", "1px solid red", important: true);
+
+ await div.SetAttributeAsync("data-customAttribute", "123");
+ await div.SetInnerTextAsync("Updated Div innerText");
+}
+
+//Using standard array
+var tableRows = await htmlTableElement.GetRowsAsync().ToArrayAsync();
+
+foreach (var row in tableRows)
+{
+ var cells = await row.GetCellsAsync().ToArrayAsync();
+ foreach (var cell in cells)
+ {
+ var newDiv = await devToolsContext.CreateHtmlElementAsync("div");
+ await newDiv.SetInnerTextAsync("New Div Added!");
+ await cell.AppendChildAsync(newDiv);
+ }
+}
+
+//Get a reference to the HtmlCollection and use async enumerable
+//Requires Net Core 3.1 or higher
+var tableRowsHtmlCollection = await htmlTableElement.GetRowsAsync();
+
+await foreach (var row in tableRowsHtmlCollection)
+{
+ var cells = await row.GetCellsAsync();
+ await foreach (var cell in cells)
+ {
+ var newDiv = await devToolsContext.CreateHtmlElementAsync("div");
+ await newDiv.SetInnerTextAsync("New Div Added!");
+ await cell.AppendChildAsync(newDiv);
+ }
+}
```
-snippet source | anchor
+snippet source | anchor
## Inject HTML
-
```cs
-await using var page = await browser.NewPageAsync();
-await page.SetContentAsync("My Receipt
");
-var result = await page.GetContentAsync();
+//Wait for Initial page load
+await chromiumWebBrowser.WaitForInitialLoadAsync();
+
+await using var devtoolsContext = await chromiumWebBrowser.CreateDevToolsContextAsync();
+await devtoolsContext.SetContentAsync("My Receipt
");
+var result = await devtoolsContext.GetContentAsync();
```
-snippet source | anchor
+snippet source | anchor
## Evaluate Javascript
@@ -112,78 +186,42 @@ var result = await page.GetContentAsync();
```cs
-await using var page = await browser.NewPageAsync();
-var seven = await page.EvaluateExpressionAsync("4 + 3");
-var someObject = await page.EvaluateFunctionAsync("(value) => ({a: value})", 5);
+await using var devtoolsContext = await chromiumWebBrowser.CreateDevToolsContextAsync();
+var seven = await devtoolsContext.EvaluateExpressionAsync("4 + 3");
+var someObject = await devtoolsContext.EvaluateFunctionAsync("(value) => ({a: value})", 5);
Console.WriteLine(someObject.a);
```
-snippet source | anchor
+snippet source | anchor
-## Wait For Selector
+## Take screenshots
+
+
```cs
-using (var page = await browser.NewPageAsync())
-{
- await page.GoToAsync("http://www.spapage.com");
- await page.WaitForSelectorAsync("div.main-content")
- await page.PdfAsync(outputFile));
-}
-```
+//Wait for Initial page load
+await chromiumWebBrowser.WaitForInitialLoadAsync();
-## Wait For Function
-```cs
-using (var page = await browser.NewPageAsync())
-{
- await page.GoToAsync("http://www.spapage.com");
- var watchDog = page.WaitForFunctionAsync("()=> window.innerWidth < 100");
- await page.SetViewportAsync(new ViewPortOptions { Width = 50, Height = 50 });
- await watchDog;
-}
-```
+await using var devToolsContext = await chromiumWebBrowser.CreateDevToolsContextAsync();
-## Connect to a remote browser
+await devToolsContext.ScreenshotAsync("file.png");
+```
+snippet source | anchor
+
+
+
```cs
-var options = new ConnectOptions()
-{
- BrowserWSEndpoint = $"wss://www.externalbrowser.io?token={apikey}"
-};
-
-var url = "https://www.google.com/";
-
-using (var browser = await PuppeteerSharp.Puppeteer.ConnectAsync(options))
+// Set Viewport
+await DevToolsContext.SetViewportAsync(new ViewPortOptions
{
- using (var page = await browser.NewPageAsync())
- {
- await page.GoToAsync(url);
- await page.PdfAsync("wot.pdf");
- }
-}
+ Width = 500,
+ Height = 500
+});
```
+snippet source | anchor
+
-# Monthly reports
- * [August 2019](http://www.hardkoded.com/blog/puppeteer-sharp-monthly-aug-2019)
- * [July 2019](http://www.hardkoded.com/blog/puppeteer-sharp-monthly-jul-2019)
- * [June 2019](http://www.hardkoded.com/blog/puppeteer-sharp-monthly-jun-2019)
- * [May 2019](http://www.hardkoded.com/blog/puppeteer-sharp-monthly-may-2019)
- * [April 2019](http://www.hardkoded.com/blog/puppeteer-sharp-monthly-apr-2019)
- * [March 2019](http://www.hardkoded.com/blog/puppeteer-sharp-monthly-mar-2019)
- * [February 2019](http://www.hardkoded.com/blog/puppeteer-sharp-monthly-feb-2019)
- * [January 2019](http://www.hardkoded.com/blog/puppeteer-sharp-monthly-jan-2019)
-
-# Backers
-
-Support us with a monthly donation and help us continue our activities. [Become a backer](https://opencollective.com/hardkoded-projects).
-
-
-
-
-
-
-
-# Thanks
-
-Thanks to [JetBrains](https://www.jetbrains.com/?from=PuppeteerSharp) for a community Resharper license to use on this project.
-
+## Generate PDF files
+Currently not supported via CefSharp.Dom, use ChromiumWebBrowser.PrintToPdfAsync instead.
diff --git a/appveyor-demo.yml b/appveyor-demo.yml
deleted file mode 100644
index 685fdbb72..000000000
--- a/appveyor-demo.yml
+++ /dev/null
@@ -1,23 +0,0 @@
-version: 1.0.{build}
-branches:
- only:
- - master
-image: Visual Studio 2019
-configuration: Release
-environment:
- matrix:
- - framework: net471
- - framework: netcoreapp3.1
-before_build:
-- ps: >-
- dotnet restore .\demos\PuppeteerSharpDemos-Local.sln
-build:
- project: .\demos\PuppeteerSharpDemos-Local.sln
- publish_nuget: true
- include_nuget_references: true
- verbosity: minimal
-test_script:
-- cmd: >-
- cd .\demos\PuppeteerSharpPdfDemo
-
- dotnet run -p PuppeteerSharpPdfDemo-Local.csproj -f %framework% auto-exit
\ No newline at end of file
diff --git a/appveyor-edge.yml b/appveyor-edge.yml
deleted file mode 100644
index b6a776b2e..000000000
--- a/appveyor-edge.yml
+++ /dev/null
@@ -1,38 +0,0 @@
-version: 1.0.{build}
-branches:
- only:
- - disabled
-image: Visual Studio 2019
-configuration: Release
-environment:
- git_access_token:
- secure: FxcQ9C8a/NgcQB5dFdZts6ZWEDT4zMhA4qPQAYwWc7huMmhmTIl1sbFEIaAWQMTL
- PUPPETEER_EXECUTABLE_PATH: C:\Program Files (x86)\Microsoft\Edge Dev\Application\msedge.exe
-install:
-- ps: >-
- cd c:\projects\puppeteer-sharp-edge\appveyor\edge
-
- .\InstallEdge.ps1
-
- cd c:\projects\puppeteer-sharp-edge
-
-before_build:
-- ps: >-
- dotnet restore .\lib\PuppeteerSharp.sln
-
- New-SelfSignedCertificate -Subject "localhost" -FriendlyName "Puppeteer" -CertStoreLocation "cert:\CurrentUser\My"
-
- Get-ChildItem -Path cert:\CurrentUSer\my | where { $_.friendlyname -eq "Puppeteer" } | Export-Certificate -FilePath C:\projects\puppeteer-sharp-edge\lib\PuppeteerSharp.TestServer\testCert.cer
-
-build:
- project: .\lib\PuppeteerSharp.sln
- publish_nuget: true
- include_nuget_references: true
- verbosity: minimal
-test_script:
-- cmd: >-
- cd .\lib\PuppeteerSharp.Tests
-
- dotnet test -f net5.0 -s test.runsettings
-cache:
- - $HOME/.nuget/packages
\ No newline at end of file
diff --git a/appveyor-fullframework.yml b/appveyor-fullframework.yml
deleted file mode 100644
index 688ee97fa..000000000
--- a/appveyor-fullframework.yml
+++ /dev/null
@@ -1,35 +0,0 @@
-version: 1.0.{build}
-branches:
- only:
- - master
-image: Visual Studio 2019
-configuration: Release
-clone_folder: C:\projects\puppeteer-sharp
-environment:
- git_access_token:
- secure: FxcQ9C8a/NgcQB5dFdZts6ZWEDT4zMhA4qPQAYwWc7huMmhmTIl1sbFEIaAWQMTL
- matrix:
- - framework: net471
-only_commits:
- files:
- - lib/PuppeteerSharp.AspNetFramework/
- - appveyor-fullframework.yml
-before_build:
-- ps: >-
- dotnet restore .\lib\PuppeteerSharp.AspNetFramework.sln
-
- New-SelfSignedCertificate -Subject "localhost" -FriendlyName "Puppeteer" -CertStoreLocation "cert:\CurrentUser\My"
-
- Get-ChildItem -Path cert:\CurrentUSer\my | where { $_.friendlyname -eq "Puppeteer" } | Export-Certificate -FilePath C:\projects\puppeteer-sharp\lib\PuppeteerSharp.TestServer\testCert.cer
-
-build:
- project: .\lib\PuppeteerSharp.AspNetFramework.sln
- publish_nuget: true
- include_nuget_references: true
- verbosity: minimal
-test: off
-artifacts:
-- path: PuppeteerSharp.AspNetFramework.*.nupkg
- name: PuppeteerSharp.AspNetFramework Package
-cache:
- - $HOME/.nuget/packages
diff --git a/appveyor-linux.yml b/appveyor-linux.yml
deleted file mode 100644
index 2339622f2..000000000
--- a/appveyor-linux.yml
+++ /dev/null
@@ -1,50 +0,0 @@
-version: 1.0.{build}
-branches:
- only:
- - master
-image: ubuntu1804
-configuration: Release
-environment:
- MOZ_WEBRENDER: 0
- git_access_token:
- secure: FxcQ9C8a/NgcQB5dFdZts6ZWEDT4zMhA4qPQAYwWc7huMmhmTIl1sbFEIaAWQMTL
- matrix:
- - framework: net5.0
- PRODUCT: CHROMIUM
- - framework: net5.0
- PRODUCT: FIREFOX
-
-before_build:
-- sh: >-
- sudo apt-get -y install gconf-service libasound2 libatk1.0-0 libc6 libcairo2 libcups2 libdbus-1-3 libexpat1 libfontconfig1 libgcc1 libgconf-2-4 libgdk-pixbuf2.0-0 libglib2.0-0 libgtk-3-0 libnspr4 libpango-1.0-0 libpangocairo-1.0-0 libstdc++6 libx11-6 libx11-xcb1 libxcb1 libxcomposite1 libxcursor1 libxdamage1 libxext6 libxfixes3 libxi6 libxrandr2 libxrender1 libxss1 libxtst6 ca-certificates fonts-liberation libappindicator1 libnss3 lsb-release xdg-utils wget xvfb
-
- dotnet restore lib/PuppeteerSharp.sln
-
- dotnet dev-certs https -ep lib/PuppeteerSharp.TestServer/testCert.cer
-
- sudo openssl x509 -inform der -in lib/PuppeteerSharp.TestServer/testCert.cer -out /usr/local/share/ca-certificates/testCert.crt -outform pem
-
- sudo update-ca-certificates
-
-build_script:
-- sh: >-
- dotnet build -f $framework ./lib/PuppeteerSharp.DevicesFetcher/PuppeteerSharp.DevicesFetcher.csproj
-
- dotnet build -f $framework ./lib/PuppeteerSharp.Tests.DumpIO/PuppeteerSharp.Tests.DumpIO.csproj
-
- dotnet build -f $framework ./lib/PuppeteerSharp.TestServer/PuppeteerSharp.TestServer.csproj
-
- dotnet build -f $framework ./lib/PuppeteerSharp.Tests/PuppeteerSharp.Tests.csproj
-
-test_script:
-- sh: >-
- Xvfb :1 -screen 5 1024x768x8 &
-
- export DISPLAY=:1.5
-
- cd lib/PuppeteerSharp.Tests
-
- dotnet test -f $framework -s test.runsettings
-
-cache:
- - $HOME/.nuget/packages
diff --git a/appveyor.yml b/appveyor.yml
index 0312b0bfe..e27f3cfea 100644
--- a/appveyor.yml
+++ b/appveyor.yml
@@ -1,46 +1,45 @@
-version: 1.0.{build}
+version: 3.0.{build}
branches:
only:
- - master
-image: Visual Studio 2019
+ - main
+image: Visual Studio 2022
configuration: Release
environment:
- git_access_token:
- secure: FxcQ9C8a/NgcQB5dFdZts6ZWEDT4zMhA4qPQAYwWc7huMmhmTIl1sbFEIaAWQMTL
matrix:
- - framework: net48
- - framework: net5.0
- - framework: net48
- ENQUEUE_ASYNC_MESSAGES: true
- - framework: net5.0
- ENQUEUE_ASYNC_MESSAGES: true
-install:
-- ps: >-
- if($env:APPVEYOR_REPO_TAG -eq 'True' -And $env:framework -eq 'netcoreapp2.0') {
- choco install docfx
- }
+ - framework: netcoreapp3.1
+
before_build:
- ps: >-
- dotnet restore .\lib\PuppeteerSharp.sln
+ dotnet restore .\lib\CefSharp.Dom.sln
New-SelfSignedCertificate -Subject "localhost" -FriendlyName "Puppeteer" -CertStoreLocation "cert:\CurrentUser\My"
- Get-ChildItem -Path cert:\CurrentUSer\my | where { $_.friendlyname -eq "Puppeteer" } | Export-Certificate -FilePath C:\projects\puppeteer-sharp\lib\PuppeteerSharp.TestServer\testCert.cer
+ Get-ChildItem -Path cert:\CurrentUSer\my | where { $_.friendlyname -eq "Puppeteer" } | Export-Certificate -FilePath .\lib\PuppeteerSharp.TestServer\testCert.cer
build:
- project: .\lib\PuppeteerSharp.sln
- publish_nuget: true
- include_nuget_references: true
+ project: .\lib\CefSharp.Dom.sln
verbosity: minimal
test_script:
- cmd: >-
cd .\lib\PuppeteerSharp.Tests
- dotnet test -f %framework% -s test.runsettings
-on_success:
-- ps: >-
- cd c:\projects\puppeteer-sharp
-
- c:\projects\puppeteer-sharp\appveyor\GenerateDocs.ps1
-cache:
- - $HOME/.nuget/packages
+ dotnet test -f %framework% -s test.runsettings --test-adapter-path:. --logger:Appveyor
+
+# Patch SDK Style `.csproj` file:
+# https://www.appveyor.com/docs/build-configuration/#net-core-csproj-files-patching
+dotnet_csproj:
+ patch: true
+ file: '**\*.csproj'
+ version_prefix: '{version}'
+
+artifacts:
+ # pushing all *.nupkg files in build directory recursively
+ - path: '**\*.nupkg'
+
+# Publish to myget.org feed
+deploy:
+ provider: NuGet
+ server: https://www.myget.org/F/cefsharp/api/v2/package
+ api_key:
+ secure: V8du2PPvMPok3Ya701jt5v2XWQgOZf52/H5wDHXBpKvXYkIIe8sonhVUy2TmEkqt
+ artifact: /.*(\.|\.s)nupkg/
\ No newline at end of file
diff --git a/appveyor/GenerateDocs.ps1 b/appveyor/GenerateDocs.ps1
deleted file mode 100644
index ebcacb071..000000000
--- a/appveyor/GenerateDocs.ps1
+++ /dev/null
@@ -1,16 +0,0 @@
-if($env:APPVEYOR_REPO_TAG -eq 'True' -And $env:framework -eq 'netcoreapp2.2' -And $env:ENQUEUE_ASYNC_MESSAGES -eq 'true') {
- git config --global credential.helper store
- Add-Content "$env:USERPROFILE\.git-credentials" "https://$($env:git_access_token):x-oauth-basic@github.com`n"
-
- git config --global user.email "dariokondratiuk@gmail.com"
- git config --global user.name "Dario Kondratiuk"
- git remote add pages https://github.com/kblok/puppeteer-sharp.git
- git fetch pages
- git checkout master
- git subtree add --prefix docs pages/gh-pages
- docfx metadata docfx_project/docfx.json
- docfx build docfx_project/docfx.json -o docs
- git add docs/* -f
- git commit -m "Docs version $($env:APPVEYOR_REPO_TAG_NAME)"
- git subtree push --prefix docs pages gh-pages
-}
\ No newline at end of file
diff --git a/appveyor/edge/ImageHelpers/ImageHelpers.psd1 b/appveyor/edge/ImageHelpers/ImageHelpers.psd1
deleted file mode 100644
index dee37963a..000000000
--- a/appveyor/edge/ImageHelpers/ImageHelpers.psd1
+++ /dev/null
@@ -1,124 +0,0 @@
-#
-# Module manifest for module 'ImageHelpers'
-#
-# Generated by: chrispat
-#
-# Generated on: 11/1/2017
-#
-
-@{
-
-# Script module or binary module file associated with this manifest.
-RootModule = 'ImageHelpers.psm1'
-
-# Version number of this module.
-ModuleVersion = '0.0.1'
-
-# Supported PSEditions
-# CompatiblePSEditions = @()
-
-# ID used to uniquely identify this module
-GUID = 'c9334909-16a1-48f1-a94a-c7baf1b961d9'
-
-# Author of this module
-Author = 'chrispat'
-
-# Company or vendor of this module
-CompanyName = 'Unknown'
-
-# Copyright statement for this module
-Copyright = '(c) 2017 chrispat. All rights reserved.'
-
-# Description of the functionality provided by this module
-Description = 'Helper functions for creating vsts images'
-
-# Minimum version of the Windows PowerShell engine required by this module
-# PowerShellVersion = ''
-
-# Name of the Windows PowerShell host required by this module
-# PowerShellHostName = ''
-
-# Minimum version of the Windows PowerShell host required by this module
-# PowerShellHostVersion = ''
-
-# Minimum version of Microsoft .NET Framework required by this module. This prerequisite is valid for the PowerShell Desktop edition only.
-# DotNetFrameworkVersion = ''
-
-# Minimum version of the common language runtime (CLR) required by this module. This prerequisite is valid for the PowerShell Desktop edition only.
-# CLRVersion = ''
-
-# Processor architecture (None, X86, Amd64) required by this module
-# ProcessorArchitecture = ''
-
-# Modules that must be imported into the global environment prior to importing this module
-# RequiredModules = @()
-
-# Assemblies that must be loaded prior to importing this module
-# RequiredAssemblies = @()
-
-# Script files (.ps1) that are run in the caller's environment prior to importing this module.
-# ScriptsToProcess = @()
-
-# Type files (.ps1xml) to be loaded when importing this module
-# TypesToProcess = @()
-
-# Format files (.ps1xml) to be loaded when importing this module
-# FormatsToProcess = @()
-
-# Modules to import as nested modules of the module specified in RootModule/ModuleToProcess
-# NestedModules = @()
-
-# Functions to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no functions to export.
-FunctionsToExport = '*'
-
-# Cmdlets to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no cmdlets to export.
-CmdletsToExport = '*'
-
-# Variables to export from this module
-VariablesToExport = '*'
-
-# Aliases to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no aliases to export.
-AliasesToExport = '*'
-
-# DSC resources to export from this module
-# DscResourcesToExport = @()
-
-# List of all modules packaged with this module
-# ModuleList = @()
-
-# List of all files packaged with this module
-# FileList = @()
-
-# Private data to pass to the module specified in RootModule/ModuleToProcess. This may also contain a PSData hashtable with additional module metadata used by PowerShell.
-PrivateData = @{
-
- PSData = @{
-
- # Tags applied to this module. These help with module discovery in online galleries.
- # Tags = @()
-
- # A URL to the license for this module.
- # LicenseUri = ''
-
- # A URL to the main website for this project.
- # ProjectUri = ''
-
- # A URL to an icon representing this module.
- # IconUri = ''
-
- # ReleaseNotes of this module
- # ReleaseNotes = ''
-
- } # End of PSData hashtable
-
-} # End of PrivateData hashtable
-
-# HelpInfo URI of this module
-# HelpInfoURI = ''
-
-# Default prefix for commands exported from this module. Override the default prefix using Import-Module -Prefix.
-# DefaultCommandPrefix = ''
-
-}
-
-
diff --git a/appveyor/edge/ImageHelpers/ImageHelpers.psm1 b/appveyor/edge/ImageHelpers/ImageHelpers.psm1
deleted file mode 100644
index 12df84e7a..000000000
--- a/appveyor/edge/ImageHelpers/ImageHelpers.psm1
+++ /dev/null
@@ -1,19 +0,0 @@
-[CmdletBinding()]
-param()
-
-. $PSScriptRoot\PathHelpers.ps1
-. $PSScriptRoot\InstallHelpers.ps1
-. $PSScriptRoot\MarkdownHelpers.ps1
-
-Export-ModuleMember -Function @(
- 'Test-MachinePath'
- 'Get-MachinePath'
- 'Set-MachinePath'
- 'Add-MachinePathItem'
- 'Get-SystemVariable'
- 'Set-SystemVariable'
- 'Install-MSI'
- 'Install-EXE'
- 'Add-ContentToMarkdown'
- 'Add-SoftwareDetailsToMarkdown'
-)
diff --git a/appveyor/edge/ImageHelpers/InstallHelpers.ps1 b/appveyor/edge/ImageHelpers/InstallHelpers.ps1
deleted file mode 100644
index 12bb373fc..000000000
--- a/appveyor/edge/ImageHelpers/InstallHelpers.ps1
+++ /dev/null
@@ -1,83 +0,0 @@
-function Install-MSI
-{
- Param
- (
- [String]$MsiUrl,
- [String]$MsiName
- )
-
- $exitCode = -1
-
- try
- {
- Write-Host "Downloading $MsiName..."
- $FilePath = "${env:Temp}\$MsiName"
-
- Invoke-WebRequest -Uri $MsiUrl -OutFile $FilePath
-
- $Arguments = ('/i', $FilePath, '/QN', '/norestart' )
-
- Write-Host "Starting Install $MsiName..."
- $process = Start-Process -FilePath msiexec.exe -ArgumentList $Arguments -Wait -PassThru
- $exitCode = $process.ExitCode
-
- if ($exitCode -eq 0 -or $exitCode -eq 3010)
- {
- Write-Host -Object 'Installation successful'
- return $exitCode
- }
- else
- {
- Write-Host -Object "Non zero exit code returned by the installation process : $exitCode."
- exit $exitCode
- }
- }
- catch
- {
- Write-Host -Object "Failed to install the MSI $MsiName"
- Write-Host -Object $_.Exception.Message
- exit -1
- }
-}
-
-
-function Install-EXE
-{
- Param
- (
- [String]$Url,
- [String]$Name,
- [String[]]$ArgumentList
- )
-
- $exitCode = -1
-
- try
- {
- Write-Host "Downloading $Name..."
- $FilePath = "${env:Temp}\$Name"
-
- Invoke-WebRequest -Uri $Url -OutFile $FilePath
-
- Write-Host "Starting Install $Name..."
- $process = Start-Process -FilePath $FilePath -ArgumentList $ArgumentList -Wait -PassThru
- $exitCode = $process.ExitCode
-
- if ($exitCode -eq 0 -or $exitCode -eq 3010)
- {
- Write-Host -Object 'Installation successful'
- return $exitCode
- }
- else
- {
- Write-Host -Object "Non zero exit code returned by the installation process : $exitCode."
- return $exitCode
- }
- }
- catch
- {
- Write-Host -Object "Failed to install the Executable $Name"
- Write-Host -Object $_.Exception.Message
- return -1
- }
-}
diff --git a/appveyor/edge/ImageHelpers/MarkdownHelpers.ps1 b/appveyor/edge/ImageHelpers/MarkdownHelpers.ps1
deleted file mode 100644
index da5d53e2c..000000000
--- a/appveyor/edge/ImageHelpers/MarkdownHelpers.ps1
+++ /dev/null
@@ -1,25 +0,0 @@
-function Add-ContentToMarkdown {
- [CmdletBinding()]
- param(
- $Content = ""
- )
-
- Add-Content 'C:\InstalledSoftware.md' $Content
-}
-
-
-function Add-SoftwareDetailsToMarkdown {
- [CmdletBinding()]
- param(
- $SoftwareName = "",
- $DescriptionMarkdown = ""
- )
-
-$Content = @"
-
-## $SoftwareName
-
-$DescriptionMarkdown
-"@
- Add-ContentToMarkdown -Content $Content
-}
diff --git a/appveyor/edge/ImageHelpers/PathHelpers.ps1 b/appveyor/edge/ImageHelpers/PathHelpers.ps1
deleted file mode 100644
index a1d818d6c..000000000
--- a/appveyor/edge/ImageHelpers/PathHelpers.ps1
+++ /dev/null
@@ -1,68 +0,0 @@
-function Test-MachinePath{
- [CmdletBinding()]
- param(
- [string]$PathItem
- )
-
- $currentPath = Get-MachinePath
-
- $pathItems = $currentPath.Split(';')
-
- if($pathItems.Contains($PathItem))
- {
- return $true
- }
- else
- {
- return $false
- }
-}
-
-function Set-MachinePath{
- [CmdletBinding()]
- param(
- [string]$NewPath
- )
- Set-ItemProperty -Path 'Registry::HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Session Manager\Environment' -Name Path -Value $NewPath
- return $NewPath
-}
-
-function Add-MachinePathItem
-{
- [CmdletBinding()]
- param(
- [string]$PathItem
- )
-
- $currentPath = Get-MachinePath
- $newPath = $PathItem + ';' + $currentPath
- return Set-MachinePath -NewPath $newPath
-}
-
-function Get-MachinePath{
- [CmdletBinding()]
- param(
-
- )
- $currentPath = (Get-ItemProperty -Path 'Registry::HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Session Manager\Environment' -Name PATH).Path
- return $currentPath
-}
-
-function Get-SystemVariable{
- [CmdletBinding()]
- param(
- [string]$SystemVariable
- )
- $currentPath = (Get-ItemProperty -Path 'Registry::HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Session Manager\Environment' -Name $SystemVariable).$SystemVariable
- return $currentPath
-}
-
-function Set-SystemVariable{
- [CmdletBinding()]
- param(
- [string]$SystemVariable,
- [string]$Value
- )
- Set-ItemProperty -Path 'Registry::HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Session Manager\Environment' -Name $SystemVariable -Value $Value
- return $Value
-}
\ No newline at end of file
diff --git a/appveyor/edge/InstallEdge.ps1 b/appveyor/edge/InstallEdge.ps1
deleted file mode 100644
index 32f01a376..000000000
--- a/appveyor/edge/InstallEdge.ps1
+++ /dev/null
@@ -1,23 +0,0 @@
-################################################################################
-## File: Install-EdgePreview.ps1
-## Team: Automated Testing
-## Desc: Install Microsoft Edge preview
-################################################################################
-#Save the current value in the $p variable.
-Copy-Item -Path .\ImageHelpers -Destination $home\Documents\WindowsPowerShell\Modules\ImageHelpers -Recurse -Force
-
-Import-Module -Name ImageHelpers -Force
-
-$temp_install_dir = 'C:\Windows\Installer'
-New-Item -Path $temp_install_dir -ItemType Directory -Force
-
-Install-EXE -Url "https://go.microsoft.com/fwlink/?linkid=2069324&Channel=Dev&language=en-us&Consent=1" -Name "MicrosoftEdgeSetup.exe" -ArgumentList "/silent /install"
-
-# Add some things to stop Edge from auto updating.
-New-NetFirewallRule -DisplayName "BlockEdgeUpdate" -Direction Outbound -Action Block -Program "C:\Program Files (x86)\Microsoft\EdgeUpdate\MicrosoftEdgeUpdate.exe"
-
-New-Item -Path "HKLM:\SOFTWARE\Policies\Microsoft\MicrosoftEdgeUpdate" -Force
-New-ItemProperty "HKLM:\SOFTWARE\Policies\Microsoft\MicrosoftEdgeUpdate" -Name "AutoUpdateCheckPeriodMinutes" -Value 00000000 -Force
-New-ItemProperty "HKLM:\SOFTWARE\Policies\Microsoft\MicrosoftEdgeUpdate" -Name "UpdateDefault" -Value 00000000 -Force
-New-ItemProperty "HKLM:\SOFTWARE\Policies\Microsoft\MicrosoftEdgeUpdate" -Name "DisableAutoUpdateChecksCheckboxValue" -Value 00000001 -Force
-New-ItemProperty "HKLM:\SOFTWARE\Policies\Microsoft\MicrosoftEdgeUpdate" -Name "Update{8A69D345-D564-463C-AFF1-A69D9E530F96}" -Value 00000000 -Force
diff --git a/demos/PuppeteerSharpDemos-Local.sln b/demos/PuppeteerSharpDemos-Local.sln
deleted file mode 100644
index a18b21626..000000000
--- a/demos/PuppeteerSharpDemos-Local.sln
+++ /dev/null
@@ -1,31 +0,0 @@
-
-Microsoft Visual Studio Solution File, Format Version 12.00
-# Visual Studio 15
-VisualStudioVersion = 15.0.27130.2036
-MinimumVisualStudioVersion = 10.0.40219.1
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PuppeteerSharpPdfDemo-Local", "PuppeteerSharpPdfDemo\PuppeteerSharpPdfDemo-Local.csproj", "{1B8CE751-9762-45DD-8AEC-A6C1D74A7730}"
-EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PuppeteerSharp", "..\lib\PuppeteerSharp\PuppeteerSharp.csproj", "{4BA6F28A-EFF2-4B43-9B5A-86333DC64C64}"
-EndProject
-Global
- GlobalSection(SolutionConfigurationPlatforms) = preSolution
- Debug|Any CPU = Debug|Any CPU
- Release|Any CPU = Release|Any CPU
- EndGlobalSection
- GlobalSection(ProjectConfigurationPlatforms) = postSolution
- {1B8CE751-9762-45DD-8AEC-A6C1D74A7730}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {1B8CE751-9762-45DD-8AEC-A6C1D74A7730}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {1B8CE751-9762-45DD-8AEC-A6C1D74A7730}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {1B8CE751-9762-45DD-8AEC-A6C1D74A7730}.Release|Any CPU.Build.0 = Release|Any CPU
- {4BA6F28A-EFF2-4B43-9B5A-86333DC64C64}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {4BA6F28A-EFF2-4B43-9B5A-86333DC64C64}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {4BA6F28A-EFF2-4B43-9B5A-86333DC64C64}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {4BA6F28A-EFF2-4B43-9B5A-86333DC64C64}.Release|Any CPU.Build.0 = Release|Any CPU
- EndGlobalSection
- GlobalSection(SolutionProperties) = preSolution
- HideSolutionNode = FALSE
- EndGlobalSection
- GlobalSection(ExtensibilityGlobals) = postSolution
- SolutionGuid = {7C1E8495-E1E4-426D-B28C-E0C0C5824B9C}
- EndGlobalSection
-EndGlobal
diff --git a/demos/PuppeteerSharpPdfDemo/Program.cs b/demos/PuppeteerSharpPdfDemo/Program.cs
deleted file mode 100644
index 030e840b3..000000000
--- a/demos/PuppeteerSharpPdfDemo/Program.cs
+++ /dev/null
@@ -1,40 +0,0 @@
-using System;
-using System.Linq;
-using System.IO;
-using System.Threading.Tasks;
-using PuppeteerSharp;
-
-namespace PuppeteerSharpPdfDemo
-{
- class MainClass
- {
- public static async Task Main(string[] args)
- {
- var options = new LaunchOptions
- {
- Headless = true
- };
-
- Console.WriteLine("Downloading chromium");
- using var browserFetcher = new BrowserFetcher();
- await browserFetcher.DownloadAsync();
-
- Console.WriteLine("Navigating google");
- using (var browser = await Puppeteer.LaunchAsync(options))
- using (var page = await browser.NewPageAsync())
- {
- await page.GoToAsync("http://www.google.com");
-
- Console.WriteLine("Generating PDF");
- await page.PdfAsync(Path.Combine(Directory.GetCurrentDirectory(), "google.pdf"));
-
- Console.WriteLine("Export completed");
-
- if (!args.Any(arg => arg == "auto-exit"))
- {
- Console.ReadLine();
- }
- }
- }
- }
-}
diff --git a/demos/PuppeteerSharpPdfDemo/PuppeteerSharpPdfDemo-Local.csproj b/demos/PuppeteerSharpPdfDemo/PuppeteerSharpPdfDemo-Local.csproj
deleted file mode 100644
index 002d82918..000000000
--- a/demos/PuppeteerSharpPdfDemo/PuppeteerSharpPdfDemo-Local.csproj
+++ /dev/null
@@ -1,14 +0,0 @@
-
-
-
- Exe
- netcoreapp3.1;net471
- 8.0
-
-
- win7-x64
-
-
-
-
-
diff --git a/docfx_project/api/index.md b/docfx_project/api/index.md
index 52c957927..4a3c32277 100644
--- a/docfx_project/api/index.md
+++ b/docfx_project/api/index.md
@@ -1,6 +1,9 @@
-# Puppeteer Sharp
+# PuppeteerSharp Embedded (CefSharp)
-Puppeteer Sharp is a .NET port of the official [Node.JS Puppeteer API](https://github.com/GoogleChrome/puppeteer).
+Puppeteer Embedded is a fork of [puppeteer-sharp by Darío Kondratiuk](https://github.com/hardkoded/puppeteer-sharp) that has been adapted specifically for use with CefSharp.
+Direct communication with the ChromiumWebBrowser instance rather than opening a web socket.
+1:1 mapping of Page and ChromiumWebBrowser
+CEF only supports a subset of features, features will be added/removed as the project matures
# Usage
diff --git a/docfx_project/index.md b/docfx_project/index.md
index 0e1ffeafa..3a5a0a4ee 100644
--- a/docfx_project/index.md
+++ b/docfx_project/index.md
@@ -1,38 +1,21 @@
-# Puppeteer Sharp
+# PuppeteerSharp Embedded (CefSharp)
-Puppeteer Sharp is a .NET port of the official [Node.JS Puppeteer API](https://github.com/GoogleChrome/puppeteer).
+Puppeteer Embedded is a fork of [puppeteer-sharp by Darío Kondratiuk](https://github.com/hardkoded/puppeteer-sharp) that has been adapted specifically for use with CefSharp.
+Direct communication with the ChromiumWebBrowser instance rather than opening a web socket.
+1:1 mapping of Page and ChromiumWebBrowser
+CEF only supports a subset of features, features will be added/removed as the project matures
+# Prerequisites
-# Puppeteer-Sharp 3 is here!
-
-Check out the [blog post](https://www.hardkoded.com/blog/puppeteer-sharp-3-is-here)!
-
-# Sponsor the project
+ * .Net 4.7.2 or .Net Core 3.1 or greater
+ * CefSharp 95.7.141 or greater
-If you are making money using Puppeteer-Sharp, consider sponsoring this project.
-This will give you priority support and code reviews (depending on the tier), and it will help this **community based** project keep moving.
-[Click here](https://github.com/sponsors/hardkoded) to sponsor this project.
+# Questions and Support
-# Prerequisites
+If you have an issue or a question:
- * As Puppeteer-Sharp is a NetStandard 2.0 library, The minimum platform versions are .NET Framework 4.6.1 and .NET Core 2.0. [Read more](https://docs.microsoft.com/en-us/dotnet/standard/net-standard).
- * The minimum Windows versions supporting the WebSocket library are Windows 8 and Windows Server 2012. [Read more](https://docs.microsoft.com/en-us/dotnet/api/system.net.websockets?redirectedfrom=MSDN&view=netframework-4.7.2).
- * Mono is required on **Linux**. Read more about installing Mono [here](https://www.mono-project.com/download/stable/#download-lin-ubuntu).
- * If you have issues running Chrome on Linux, the Puppeteer repo has a [great troubleshooting guide](https://github.com/GoogleChrome/puppeteer/blob/master/docs/troubleshooting.md).
-
-# Monthly reports
- * [August 2019](http://www.hardkoded.com/blog/puppeteer-sharp-monthly-aug-2019)
- * [July 2019](http://www.hardkoded.com/blog/puppeteer-sharp-monthly-jul-2019)
- * [June 2019](http://www.hardkoded.com/blog/puppeteer-sharp-monthly-jun-2019)
- * [May 2019](http://www.hardkoded.com/blog/puppeteer-sharp-monthly-may-2019)
- * [April 2019](http://www.hardkoded.com/blog/puppeteer-sharp-monthly-apr-2019)
- * [March 2019](http://www.hardkoded.com/blog/puppeteer-sharp-monthly-mar-2019)
- * [February 2019](http://www.hardkoded.com/blog/puppeteer-sharp-monthly-feb-2019)
- * [January 2019](http://www.hardkoded.com/blog/puppeteer-sharp-monthly-jan-2019)
+* Ask a question on [Discussions](https://github.com/cefsharp/PuppeteerSharp.Embedded/discussions).
# Useful links
-* [GitHub-Repo](https://github.com/hardkoded/puppeteer-sharp)
-* Slack channel [#puppeteer-sharp](https://www.hardkoded.com/goto/pptr-slack)
-* [StackOverflow](https://stackoverflow.com/search?q=puppeteer-sharp)
-* [Issues](https://github.com/kblok/puppeteer-sharp/issues?utf8=%E2%9C%93&q=is%3Aissue)
+* [Puppeteer-Sharp GitHub-Repo](https://github.com/hardkoded/puppeteer-sharp)
diff --git a/demos/PuppeteerSharpDemos.sln b/lib/CefSharp.Dom.OutOfProcess.sln
similarity index 51%
rename from demos/PuppeteerSharpDemos.sln
rename to lib/CefSharp.Dom.OutOfProcess.sln
index 167465c79..58518e8cd 100644
--- a/demos/PuppeteerSharpDemos.sln
+++ b/lib/CefSharp.Dom.OutOfProcess.sln
@@ -1,9 +1,9 @@
-
+
Microsoft Visual Studio Solution File, Format Version 12.00
-# Visual Studio 15
-VisualStudioVersion = 15.0.27130.2036
+# Visual Studio Version 16
+VisualStudioVersion = 16.0.32510.428
MinimumVisualStudioVersion = 10.0.40219.1
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PuppeteerSharpPdfDemo", "PuppeteerSharpPdfDemo\PuppeteerSharpPdfDemo.csproj", "{1B8CE751-9762-45DD-8AEC-A6C1D74A7730}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CefSharp.Dom.OutOfProcess", "PuppeteerSharp\CefSharp.Dom.OutOfProcess.csproj", "{DDAA533B-BAD2-4EC0-8F91-DED3C7C9F1B1}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
@@ -11,15 +11,15 @@ Global
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
- {1B8CE751-9762-45DD-8AEC-A6C1D74A7730}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {1B8CE751-9762-45DD-8AEC-A6C1D74A7730}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {1B8CE751-9762-45DD-8AEC-A6C1D74A7730}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {1B8CE751-9762-45DD-8AEC-A6C1D74A7730}.Release|Any CPU.Build.0 = Release|Any CPU
+ {DDAA533B-BAD2-4EC0-8F91-DED3C7C9F1B1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {DDAA533B-BAD2-4EC0-8F91-DED3C7C9F1B1}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {DDAA533B-BAD2-4EC0-8F91-DED3C7C9F1B1}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {DDAA533B-BAD2-4EC0-8F91-DED3C7C9F1B1}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
- SolutionGuid = {7C1E8495-E1E4-426D-B28C-E0C0C5824B9C}
+ SolutionGuid = {BE091CAC-CDFC-4EE8-87E7-0EE85DC98FBA}
EndGlobalSection
EndGlobal
diff --git a/lib/CefSharp.Dom.WinForms.Example/BrowserForm.Designer.cs b/lib/CefSharp.Dom.WinForms.Example/BrowserForm.Designer.cs
new file mode 100644
index 000000000..fddca34b1
--- /dev/null
+++ b/lib/CefSharp.Dom.WinForms.Example/BrowserForm.Designer.cs
@@ -0,0 +1,253 @@
+namespace CefSharp.Dom.WinForms.Example
+{
+ partial class BrowserForm
+ {
+ ///
+ /// Required designer variable.
+ ///
+ private System.ComponentModel.IContainer components = null;
+
+ ///
+ /// Clean up any resources being used.
+ ///
+ /// true if managed resources should be disposed; otherwise, false.
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing && (components != null))
+ {
+ components.Dispose();
+ }
+ base.Dispose(disposing);
+ }
+
+ #region Windows Form Designer generated code
+
+ ///
+ /// Required method for Designer support - do not modify
+ /// the contents of this method with the code editor.
+ ///
+ private void InitializeComponent()
+ {
+ System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(BrowserForm));
+ this.toolStripContainer = new System.Windows.Forms.ToolStripContainer();
+ this.statusLabel = new System.Windows.Forms.Label();
+ this.outputLabel = new System.Windows.Forms.Label();
+ this.toolStrip1 = new System.Windows.Forms.ToolStrip();
+ this.backButton = new System.Windows.Forms.ToolStripButton();
+ this.forwardButton = new System.Windows.Forms.ToolStripButton();
+ this.urlTextBox = new System.Windows.Forms.ToolStripTextBox();
+ this.goButton = new System.Windows.Forms.ToolStripButton();
+ this.menuStrip1 = new System.Windows.Forms.MenuStrip();
+ this.fileToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+ this.showDevToolsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+ this.exitToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+ this.devToolsExampleToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+ this.highlightLinksToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+ this.waitForSelectorToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+ this.toolStripContainer.ContentPanel.SuspendLayout();
+ this.toolStripContainer.TopToolStripPanel.SuspendLayout();
+ this.toolStripContainer.SuspendLayout();
+ this.toolStrip1.SuspendLayout();
+ this.menuStrip1.SuspendLayout();
+ this.SuspendLayout();
+ //
+ // toolStripContainer
+ //
+ //
+ // toolStripContainer.ContentPanel
+ //
+ this.toolStripContainer.ContentPanel.Controls.Add(this.statusLabel);
+ this.toolStripContainer.ContentPanel.Controls.Add(this.outputLabel);
+ this.toolStripContainer.ContentPanel.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3);
+ this.toolStripContainer.ContentPanel.Size = new System.Drawing.Size(852, 516);
+ this.toolStripContainer.Dock = System.Windows.Forms.DockStyle.Fill;
+ this.toolStripContainer.LeftToolStripPanelVisible = false;
+ this.toolStripContainer.Location = new System.Drawing.Point(0, 24);
+ this.toolStripContainer.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3);
+ this.toolStripContainer.Name = "toolStripContainer";
+ this.toolStripContainer.RightToolStripPanelVisible = false;
+ this.toolStripContainer.Size = new System.Drawing.Size(852, 541);
+ this.toolStripContainer.TabIndex = 0;
+ this.toolStripContainer.Text = "toolStripContainer1";
+ //
+ // toolStripContainer.TopToolStripPanel
+ //
+ this.toolStripContainer.TopToolStripPanel.Controls.Add(this.toolStrip1);
+ //
+ // statusLabel
+ //
+ this.statusLabel.AutoSize = true;
+ this.statusLabel.Dock = System.Windows.Forms.DockStyle.Bottom;
+ this.statusLabel.Location = new System.Drawing.Point(0, 486);
+ this.statusLabel.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
+ this.statusLabel.Name = "statusLabel";
+ this.statusLabel.Size = new System.Drawing.Size(0, 15);
+ this.statusLabel.TabIndex = 1;
+ //
+ // outputLabel
+ //
+ this.outputLabel.AutoSize = true;
+ this.outputLabel.Dock = System.Windows.Forms.DockStyle.Bottom;
+ this.outputLabel.Location = new System.Drawing.Point(0, 501);
+ this.outputLabel.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
+ this.outputLabel.Name = "outputLabel";
+ this.outputLabel.Size = new System.Drawing.Size(0, 15);
+ this.outputLabel.TabIndex = 0;
+ //
+ // toolStrip1
+ //
+ this.toolStrip1.Dock = System.Windows.Forms.DockStyle.None;
+ this.toolStrip1.GripStyle = System.Windows.Forms.ToolStripGripStyle.Hidden;
+ this.toolStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
+ this.backButton,
+ this.forwardButton,
+ this.urlTextBox,
+ this.goButton});
+ this.toolStrip1.Location = new System.Drawing.Point(0, 0);
+ this.toolStrip1.Name = "toolStrip1";
+ this.toolStrip1.Padding = new System.Windows.Forms.Padding(0);
+ this.toolStrip1.Size = new System.Drawing.Size(852, 25);
+ this.toolStrip1.Stretch = true;
+ this.toolStrip1.TabIndex = 0;
+ this.toolStrip1.Layout += new System.Windows.Forms.LayoutEventHandler(this.HandleToolStripLayout);
+ //
+ // backButton
+ //
+ this.backButton.Enabled = false;
+ this.backButton.Image = global::CefSharp.Dom.WinForms.Example.Properties.Resources.nav_left_green;
+ this.backButton.ImageTransparentColor = System.Drawing.Color.Magenta;
+ this.backButton.Name = "backButton";
+ this.backButton.Size = new System.Drawing.Size(52, 22);
+ this.backButton.Text = "Back";
+ this.backButton.Click += new System.EventHandler(this.BackButtonClick);
+ //
+ // forwardButton
+ //
+ this.forwardButton.Enabled = false;
+ this.forwardButton.Image = global::CefSharp.Dom.WinForms.Example.Properties.Resources.nav_right_green;
+ this.forwardButton.ImageTransparentColor = System.Drawing.Color.Magenta;
+ this.forwardButton.Name = "forwardButton";
+ this.forwardButton.Size = new System.Drawing.Size(70, 22);
+ this.forwardButton.Text = "Forward";
+ this.forwardButton.Click += new System.EventHandler(this.ForwardButtonClick);
+ //
+ // urlTextBox
+ //
+ this.urlTextBox.AutoSize = false;
+ this.urlTextBox.Name = "urlTextBox";
+ this.urlTextBox.Size = new System.Drawing.Size(500, 25);
+ this.urlTextBox.KeyUp += new System.Windows.Forms.KeyEventHandler(this.UrlTextBoxKeyUp);
+ //
+ // goButton
+ //
+ this.goButton.Image = global::CefSharp.Dom.WinForms.Example.Properties.Resources.nav_plain_green;
+ this.goButton.ImageTransparentColor = System.Drawing.Color.Magenta;
+ this.goButton.Name = "goButton";
+ this.goButton.Size = new System.Drawing.Size(42, 22);
+ this.goButton.Text = "Go";
+ this.goButton.Click += new System.EventHandler(this.GoButtonClick);
+ //
+ // menuStrip1
+ //
+ this.menuStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
+ this.fileToolStripMenuItem,
+ this.devToolsExampleToolStripMenuItem});
+ this.menuStrip1.Location = new System.Drawing.Point(0, 0);
+ this.menuStrip1.Name = "menuStrip1";
+ this.menuStrip1.Padding = new System.Windows.Forms.Padding(7, 2, 0, 2);
+ this.menuStrip1.Size = new System.Drawing.Size(852, 24);
+ this.menuStrip1.TabIndex = 1;
+ this.menuStrip1.Text = "menuStrip1";
+ //
+ // fileToolStripMenuItem
+ //
+ this.fileToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
+ this.showDevToolsToolStripMenuItem,
+ this.exitToolStripMenuItem});
+ this.fileToolStripMenuItem.Name = "fileToolStripMenuItem";
+ this.fileToolStripMenuItem.Size = new System.Drawing.Size(37, 20);
+ this.fileToolStripMenuItem.Text = "File";
+ //
+ // showDevToolsToolStripMenuItem
+ //
+ this.showDevToolsToolStripMenuItem.Name = "showDevToolsToolStripMenuItem";
+ this.showDevToolsToolStripMenuItem.Size = new System.Drawing.Size(153, 22);
+ this.showDevToolsToolStripMenuItem.Text = "Show DevTools";
+ this.showDevToolsToolStripMenuItem.Click += new System.EventHandler(this.ShowDevToolsMenuItemClick);
+ //
+ // exitToolStripMenuItem
+ //
+ this.exitToolStripMenuItem.Name = "exitToolStripMenuItem";
+ this.exitToolStripMenuItem.Size = new System.Drawing.Size(153, 22);
+ this.exitToolStripMenuItem.Text = "Exit";
+ this.exitToolStripMenuItem.Click += new System.EventHandler(this.ExitMenuItemClick);
+ //
+ // devToolsExampleToolStripMenuItem
+ //
+ this.devToolsExampleToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
+ this.highlightLinksToolStripMenuItem,
+ this.waitForSelectorToolStripMenuItem});
+ this.devToolsExampleToolStripMenuItem.Name = "devToolsExampleToolStripMenuItem";
+ this.devToolsExampleToolStripMenuItem.Size = new System.Drawing.Size(114, 20);
+ this.devToolsExampleToolStripMenuItem.Text = "DevTools Example";
+ //
+ // highlightLinksToolStripMenuItem
+ //
+ this.highlightLinksToolStripMenuItem.Name = "highlightLinksToolStripMenuItem";
+ this.highlightLinksToolStripMenuItem.Size = new System.Drawing.Size(180, 22);
+ this.highlightLinksToolStripMenuItem.Text = "Highlight Links";
+ this.highlightLinksToolStripMenuItem.Click += new System.EventHandler(this.HighlightLinksToolStripMenuItemClick);
+ //
+ // waitForSelectorToolStripMenuItem
+ //
+ this.waitForSelectorToolStripMenuItem.Name = "waitForSelectorToolStripMenuItem";
+ this.waitForSelectorToolStripMenuItem.Size = new System.Drawing.Size(180, 22);
+ this.waitForSelectorToolStripMenuItem.Text = "Wait for Selector";
+ this.waitForSelectorToolStripMenuItem.Click += new System.EventHandler(this.OnWaitForSelectorToolStripMenuItemClick);
+ //
+ // BrowserForm
+ //
+ this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 15F);
+ this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+ this.ClientSize = new System.Drawing.Size(852, 565);
+ this.Controls.Add(this.toolStripContainer);
+ this.Controls.Add(this.menuStrip1);
+ this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon")));
+ this.MainMenuStrip = this.menuStrip1;
+ this.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3);
+ this.Name = "BrowserForm";
+ this.Text = "BrowserForm";
+ this.toolStripContainer.ContentPanel.ResumeLayout(false);
+ this.toolStripContainer.ContentPanel.PerformLayout();
+ this.toolStripContainer.TopToolStripPanel.ResumeLayout(false);
+ this.toolStripContainer.TopToolStripPanel.PerformLayout();
+ this.toolStripContainer.ResumeLayout(false);
+ this.toolStripContainer.PerformLayout();
+ this.toolStrip1.ResumeLayout(false);
+ this.toolStrip1.PerformLayout();
+ this.menuStrip1.ResumeLayout(false);
+ this.menuStrip1.PerformLayout();
+ this.ResumeLayout(false);
+ this.PerformLayout();
+
+ }
+
+ #endregion
+
+ private System.Windows.Forms.ToolStripContainer toolStripContainer;
+ private System.Windows.Forms.ToolStrip toolStrip1;
+ private System.Windows.Forms.ToolStripButton backButton;
+ private System.Windows.Forms.ToolStripButton forwardButton;
+ private System.Windows.Forms.ToolStripTextBox urlTextBox;
+ private System.Windows.Forms.ToolStripButton goButton;
+ private System.Windows.Forms.MenuStrip menuStrip1;
+ private System.Windows.Forms.ToolStripMenuItem fileToolStripMenuItem;
+ private System.Windows.Forms.ToolStripMenuItem exitToolStripMenuItem;
+ private System.Windows.Forms.Label outputLabel;
+ private System.Windows.Forms.Label statusLabel;
+ private System.Windows.Forms.ToolStripMenuItem showDevToolsToolStripMenuItem;
+ private System.Windows.Forms.ToolStripMenuItem devToolsExampleToolStripMenuItem;
+ private System.Windows.Forms.ToolStripMenuItem highlightLinksToolStripMenuItem;
+ private System.Windows.Forms.ToolStripMenuItem waitForSelectorToolStripMenuItem;
+ }
+}
diff --git a/lib/CefSharp.Dom.WinForms.Example/BrowserForm.cs b/lib/CefSharp.Dom.WinForms.Example/BrowserForm.cs
new file mode 100644
index 000000000..239d7d53a
--- /dev/null
+++ b/lib/CefSharp.Dom.WinForms.Example/BrowserForm.cs
@@ -0,0 +1,240 @@
+// Copyright © 2022 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 CefSharp.Dom.WinForms.Example.Controls;
+using CefSharp.WinForms;
+using System;
+using System.Threading;
+using System.Threading.Tasks;
+using System.Windows.Forms;
+
+namespace CefSharp.Dom.WinForms.Example
+{
+ public partial class BrowserForm : Form
+ {
+#if DEBUG
+ private const string Build = "Debug";
+#else
+ private const string Build = "Release";
+#endif
+ private readonly string title = "CefSharp.Dom.WinForms.Example (" + Build + ")";
+ private readonly ChromiumWebBrowser browser;
+
+ public BrowserForm()
+ {
+ InitializeComponent();
+
+ Text = title;
+ WindowState = FormWindowState.Maximized;
+
+ browser = new ChromiumWebBrowser("www.google.com");
+ toolStripContainer.ContentPanel.Controls.Add(browser);
+
+ browser.IsBrowserInitializedChanged += OnIsBrowserInitializedChanged;
+ browser.LoadingStateChanged += OnLoadingStateChanged;
+ browser.ConsoleMessage += OnBrowserConsoleMessage;
+ browser.StatusMessage += OnBrowserStatusMessage;
+ browser.TitleChanged += OnBrowserTitleChanged;
+ browser.AddressChanged += OnBrowserAddressChanged;
+ browser.LoadError += OnBrowserLoadError;
+
+ var version = string.Format("Chromium: {0}, CEF: {1}, CefSharp: {2}",
+ Cef.ChromiumVersion, Cef.CefVersion, Cef.CefSharpVersion);
+
+#if NETCOREAPP
+ // .NET Core
+ var environment = string.Format("Environment: {0}, Runtime: {1}",
+ System.Runtime.InteropServices.RuntimeInformation.ProcessArchitecture.ToString().ToLowerInvariant(),
+ System.Runtime.InteropServices.RuntimeInformation.FrameworkDescription);
+#else
+ // .NET Framework
+ var bitness = Environment.Is64BitProcess ? "x64" : "x86";
+ var environment = String.Format("Environment: {0}", bitness);
+#endif
+
+ DisplayOutput(string.Format("{0}, {1}", version, environment));
+ }
+
+ private void OnBrowserLoadError(object sender, LoadErrorEventArgs e)
+ {
+ //Actions that trigger a download will raise an aborted error.
+ //Aborted is generally safe to ignore
+ if (e.ErrorCode == CefErrorCode.Aborted)
+ {
+ return;
+ }
+
+ var errorHtml = string.Format("Failed to load URL {0} with error {1} ({2}). ",
+ e.FailedUrl, e.ErrorText, e.ErrorCode);
+
+ _ = e.Browser.SetMainFrameDocumentContentAsync(errorHtml);
+
+ //AddressChanged isn't called for failed Urls so we need to manually update the Url TextBox
+ this.InvokeOnUiThreadIfRequired(() => urlTextBox.Text = e.FailedUrl);
+ }
+
+ private void OnIsBrowserInitializedChanged(object sender, EventArgs e)
+ {
+ var b = ((ChromiumWebBrowser)sender);
+
+ this.InvokeOnUiThreadIfRequired(() => b.Focus());
+ }
+
+ private void OnBrowserConsoleMessage(object sender, ConsoleMessageEventArgs args)
+ {
+ DisplayOutput(string.Format("Line: {0}, Source: {1}, Message: {2}", args.Line, args.Source, args.Message));
+ }
+
+ private void OnBrowserStatusMessage(object sender, StatusMessageEventArgs args)
+ {
+ this.InvokeOnUiThreadIfRequired(() => statusLabel.Text = args.Value);
+ }
+
+ private void OnLoadingStateChanged(object sender, LoadingStateChangedEventArgs args)
+ {
+ SetCanGoBack(args.CanGoBack);
+ SetCanGoForward(args.CanGoForward);
+
+ this.InvokeOnUiThreadIfRequired(() => SetIsLoading(!args.CanReload));
+ }
+
+ private void OnBrowserTitleChanged(object sender, TitleChangedEventArgs args)
+ {
+ this.InvokeOnUiThreadIfRequired(() => Text = title + " - " + args.Title);
+ }
+
+ private void OnBrowserAddressChanged(object sender, AddressChangedEventArgs args)
+ {
+ this.InvokeOnUiThreadIfRequired(() => urlTextBox.Text = args.Address);
+ }
+
+ private void SetCanGoBack(bool canGoBack)
+ {
+ this.InvokeOnUiThreadIfRequired(() => backButton.Enabled = canGoBack);
+ }
+
+ private void SetCanGoForward(bool canGoForward)
+ {
+ this.InvokeOnUiThreadIfRequired(() => forwardButton.Enabled = canGoForward);
+ }
+
+ private void SetIsLoading(bool isLoading)
+ {
+ goButton.Text = isLoading ?
+ "Stop" :
+ "Go";
+ goButton.Image = isLoading ?
+ Properties.Resources.nav_plain_red :
+ Properties.Resources.nav_plain_green;
+
+ HandleToolStripLayout();
+ }
+
+ public void DisplayOutput(string output)
+ {
+ this.InvokeOnUiThreadIfRequired(() => outputLabel.Text = output);
+ }
+
+ private void HandleToolStripLayout(object sender, LayoutEventArgs e)
+ {
+ HandleToolStripLayout();
+ }
+
+ private void HandleToolStripLayout()
+ {
+ var width = toolStrip1.Width;
+ foreach (ToolStripItem item in toolStrip1.Items)
+ {
+ if (item != urlTextBox)
+ {
+ width -= item.Width - item.Margin.Horizontal;
+ }
+ }
+ urlTextBox.Width = Math.Max(0, width - urlTextBox.Margin.Horizontal - 18);
+ }
+
+ private void ExitMenuItemClick(object sender, EventArgs e)
+ {
+ browser.Dispose();
+ Cef.Shutdown();
+ Close();
+ }
+
+ private void GoButtonClick(object sender, EventArgs e)
+ {
+ LoadUrl(urlTextBox.Text);
+ }
+
+ private void BackButtonClick(object sender, EventArgs e)
+ {
+ browser.Back();
+ }
+
+ private void ForwardButtonClick(object sender, EventArgs e)
+ {
+ browser.Forward();
+ }
+
+ private void UrlTextBoxKeyUp(object sender, KeyEventArgs e)
+ {
+ if (e.KeyCode != Keys.Enter)
+ {
+ return;
+ }
+
+ LoadUrl(urlTextBox.Text);
+ }
+
+ private void LoadUrl(string url)
+ {
+ if (Uri.IsWellFormedUriString(url, UriKind.RelativeOrAbsolute))
+ {
+ browser.Load(url);
+ }
+ }
+
+ private void ShowDevToolsMenuItemClick(object sender, EventArgs e)
+ {
+ browser.ShowDevTools();
+ }
+
+ private async void HighlightLinksToolStripMenuItemClick(object sender, EventArgs e)
+ {
+ var devToolsContext = await browser.CreateDevToolsContextAsync();
+
+ var links = await devToolsContext.QuerySelectorAllAsync("a");
+
+ var previousColor = await links[0].GetStyleAsync().AndThen(x => x.GetPropertyValueAsync("background-color"));
+
+ var color = previousColor == "yellow" ? "red" : "yellow";
+
+ foreach (var link in links)
+ {
+ await link.GetStyleAsync().AndThen(x => x.SetPropertyAsync("background-color", color));
+ }
+
+ await devToolsContext.DisposeAsync();
+ }
+
+ private async void OnWaitForSelectorToolStripMenuItemClick(object sender, EventArgs e)
+ {
+ _ = await browser.LoadUrlAsync("https://developers.google.com/web/");
+
+ var devToolsContext = await browser.CreateDevToolsContextAsync();
+
+ var inputSelector = "input[name='q']";
+ var waitForSelectorOptions = new WaitForSelectorOptions { Timeout = 30000 };
+ var emailInput = await devToolsContext.WaitForSelectorAsync(inputSelector, waitForSelectorOptions);
+ await emailInput.TypeAsync("Headless");
+
+ // Artifically sleep a little for demo purposes
+ await Task.Delay(5000);
+
+ var emailInput1 = await devToolsContext.WaitForSelectorAsync(inputSelector, waitForSelectorOptions);
+ await emailInput1.TypeAsync(" Chrome");
+
+ await devToolsContext.DisposeAsync();
+ }
+ }
+}
diff --git a/lib/CefSharp.Dom.WinForms.Example/BrowserForm.resx b/lib/CefSharp.Dom.WinForms.Example/BrowserForm.resx
new file mode 100644
index 000000000..bcb9f497e
--- /dev/null
+++ b/lib/CefSharp.Dom.WinForms.Example/BrowserForm.resx
@@ -0,0 +1,487 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ 17, 17
+
+
+ 122, 17
+
+
+
+
+ AAABAAcAMDAAAAEACACoDgAAdgAAACAgAAABAAgAqAgAAB4PAAAQEAAAAQAIAGgFAADGFwAAMDAAAAEA
+ IACoJQAALh0AACAgAAABACAAqBAAANZCAAAYGAAAAQAgAIgJAAB+UwAAEBAAAAEAIABoBAAABl0AACgA
+ AAAwAAAAYAAAAAEACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA////AAAAAADqlE0Ad3Z+ADg3
+ OwA2NTkAPj1BAF5dYQC6ub0ANDM2AFdWWQChn6MAa2psAJwc/wCdI/kAnSLxAKQ07ACpTeYAqWrQALaH
+ 0QDBndQAmivPAK2QuwBlY2YApDzQALti4wCyWNAAwW3PAKRLsQC2rLcAlzmbAEtJSwBzcXMAnUaZALtx
+ tgCkV5oAynq9AJQ8fACLUHMAzIyyAKhnjADVucEAOjY3AJGNjgDRlaIAqqOkAM6hpACaWVkAxcLCAOip
+ oQCEf34AUUZDANGqngC2s7IAWzIfAFY5LABCOzgAZDYeAGQ8KACndFoAqnpjALWajABhVU8AxL67ANbU
+ 0wCLTSoAj1AsAI1OKwCVVC8AkFMxAJJXNgCVWjgAlVs6AJdePgCeaUsAoG1QAKJvUwCVZk0Ai2JLAK6A
+ ZgDLtKcA0LuwAIxOKgCcWzMAnGVCAH5bRQCyiXAAwJZ8AJ6AbgC+nosAxaaUANjGuwDOycYAWUg9AKOJ
+ dwCNeGoA0busANXDtwDX0c0AbU43ALOIZwCZd14Ah2lTAE1ANgDHrpwAv7GnANDIwgDp4t0Avbm2AO7q
+ 5wDplE0A6JNNAOKPSwDqlE4A55NNAOaTTgDkkk4A65dRAOGRTgDekE8A2o5PAOydWgDVjVEAuH5QANWU
+ XgDtpWkAsXxPAKl2TADenGUA5KJrAO2sdgDvsX4A26Z6AOuzhADhrYIA7L2VAM+nhQD0yqcArJB5APTQ
+ sgD10rUA38GpAPLWvwDdx7UA89vIAO3WwwDl2c8A2s/GANnOxQDYzcQA18zDAMzDvADKwboAyL+4ANbN
+ xgCxq6YAycO+AMfBvAC9t7IA1M7JANLMxwDLxcAA493YAO3n4gDAu7cA6JRGAOmWSgDpl0wA6phPAM+H
+ SADrmlQA4phVAOyiYQDOjVUA7atuAMqWaQDwuYYAyp95APHAlABwWUUA0q6OANSylAB+cGMA48y4AN/U
+ ygDe08kA3dLIANzRxwDb0MYA2s/FAOLXzQDTycAA0si/AM3EvADMw7sAycC4AOXc1ADa0ckAxb22AMK6
+ swDe1s8A3NTNANfPyADRysQA5ZRBAOuoZADMlF8A05xoAOHWywDVy8EAz8a9AN3UywDp4NcAysS+ALm1
+ sQC1sa0A8+7pAO3p5QDPzMkA9vTyAOKQNwDfnlgA77Z7AI5yVADyx5gAeWlXAKp0MQB7WjEAuJVsANyN
+ KADank0Am2kgALqCMQDFizUAuIpKAJd2SABaSC0A0IUSALJ2FQDBiCoA1ZYyAIVfJQDXmz8A4axWAIlq
+ OgCog0oAimw9AOOzaQDy06MAfX2GAFFRVQDOztQARUVHANvb4AD///8AAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC+1tVpmZmpsyaChzF1dAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAC2ibKJ4LTEbMnKysbLoaBrop2dAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAtomysli0LKPU1NTGxsubY8uhzKLbQG0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAADWJsrCJZV42
+ xby8vZSVlpeiy8xra2vbnUAxHgAAAAAAAAAAAAAAAAAAAAAAAAAAtbKwsIVlXgnFu7u8vLy9lJWWmKJd
+ ol3Wop0xpdcAAAAAAAAAAAAAAAAAAAAAAACJss+ufeVeCcW5ubq6u7y8vL2+lpfS02uZx23bQKXXAAAA
+ AAAAAAAAAAAAAAAAALKwz66uiV4sbL+/0dG5ubq7vLy9lJWX0sHTmW3InkCl1wAAAAAAAAAAAAAAAAAA
+ srDPrnt75CAM1ZO/v7/R0bm6u7y8vZSVl9LBwsSf18hAbdcAAAAAAAAAAAAAAACysNB9e3t45AssbmyT
+ k5O/v9HRubq7vLyUlZfSwcKZyNefpW3YAAAAAAAAAAAAAFiw0H17eXh3quIEDUHak5OTk7+/0bm6u7y8
+ vZWX0sHCxMjY16XX2AAAAAAAAAAAALDQ0Ht5eHd1daq3IQs22cWTk5O/v9G5uru8vJSVl9LBw5rI2Nht
+ 1wAAAAAAAAAAz8+Fe3l4d3V0c3CqYAT7LNnVk5OTv7/Rubq7vLyUlZfA05nHnzbYn9gAAAAAAAAAroWB
+ eXh3dXRzcG9vcWb6CA2jbJOTk5PR0bm6u7y9vpbSwcKZx9fY2NceAAAAAACF0IV5eHd1c3NwbwMDAwN8
+ MyELXdmkpKRsxdG5uru8vb6X0sHDmsg22NfYAAAAAADQh4F4d3VzcG9vAwMDA29yhSwE+wzcbm5ubtrV
+ 0bq8vL2Vl8DTmcef2Jw2AAAAAC19hnh3dXRzb28DAwMDb62Kj5Kc+ggzDG3bbtpupJO7vL2UltLBwprI
+ 19ic2AAAAIeBh3d1dHNwbwMDAwNvg42PuF+0GAgHBwf9CNjabtrFu7y9lZfA05nHn9ic2AAAAIeGgnd1
+ c3BvAwMDA3KDj49ptDkFCgoKCgoKCgcN227ak7y8lJbSwcKayNicnAAAAIWIrHVzcG8DAwMDcq2Njz5e
+ Bis5aGhoaO05CgoG+9vapNS8vZWXwNOZx9fYLgAAAIGIdXRwb28DAwNyq7OPW14raLTk8ujo6PLo7TkK
+ BQtA2tW8vJSW0sHDx9fXLgAAAIOGdXNwbwMDAwOrfo+4tAZeVvLo7+7u7u7u6PLtCgUNo9q5vL2Vl8HC
+ mp/Y2C4AAIKGc3BvAwMDA3Z6s5GLOWhW8u/u7u7m5ubu7uP17Qr9nNrFvL2+l9LTmcht2C4AAIKGc29v
+ AwMDcqutjJJWBj/37+7u5t2mps3d5u7P92gFM9psvLyUltLBw8fY2AAAAH6GcG8DAwMDdq1+kZBkCrfo
+ 7u7mpqutzq2rzebu5eQ5GGyku7y9ldLBwprDnAAAAIKEcG8DAwNyen6vkWleCuDp5ubNeq/f39/Oq93u
+ 0PdoGKDau7y9lZfAm54hMwAAAISxbwMDAwOren6DkWk0Cvfq5uapft+z4bPfrabm5/btGKDaury9vMlA
+ LCD9LAAAALOEqwMDA3J6fq+EkWk/Cvfq892rr7H5+eHfzqjm+OtkDWza1cUxDCH7CyD9LgAAAACDfgMD
+ A3Z6foOEj2I/C/Lw9N12zrHh+eHfzqjm+Om3LEE2+hgI+yA0Xl4LHgAAAACEhAMDA6utr4OxjGoEBGTv
+ +M2mrYOxsd+ves3n8+sLCPsgNDQ4ODtWZkw+AAAAAACxhHYDcnp+r4Sx4TMuPz/y8fjOq62vr696qObx
+ 87c4ODc6ZE9PTkxHQkpqAAAAAAAAg34Ddnp+g4SGWQxATzTi5Or4zqurq6lz5u7x7Ds+UVpMVUJCQkJC
+ Qj0AAAAAAAAAsYMDeoqxhIw+DB5SYmQ04uzr597erKro8uziNz5hW0ZCQkJCQkJCQmkAAAAAAAAAAIR+
+ hIqMjWEECT5MUWJWaAtngIB/41VnCDQ7PmFRS0JCQkJCQkJCTQAAAAAAAAAAADKEg4qNjGAMMU1CS1Fc
+ XztoIPsICDRoN1ZSYVFLQkJCQkJCQlNTPgAAAAAAAAAAAACxsYqMjjT8akZCQklaYWI+Zzs3N1ZZaWJR
+ WklCQkJCQkJTRERMAAAAAAAAAAAAAAAAs7OMPiD+UUpTQkJETFpRUmJiYmJhUVpMREJCQlNTREREREYA
+ AAAAAAAAAAAAAAAAAOGxLCAsaVVERERTU1NHTT1XVz1NR1NTU1NEREREQ0VFRAAAAAAAAAAAAAAAAAAA
+ AACKX/0zW01HRERERERERERERERERERERERERERDVFRDAAAAAAAAAAAAAAAAAAAAAAAAKrRgSltaS0RE
+ REREREREREREREREREREQ0VUVEgAAAAAAAAAAAAAAAAAAAAAAAAAAAAATVdbW1VGQ0NDQ0NDQ0NDQ0ND
+ RkVHVVVVMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAATE09V0tKSklJSUhISEhISUlKVUxNgEsAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAA9PD1QPTxMS0tLS0tMTTw9PIA8AAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAA9PVBXV1dXV1dXUD09AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAA////////3P3////////c/f//AAP//9z9//wAAH//3P3/8AAAH//c/f/AAAAH/9z9/4AAAAP/
+ 3P3/AAAAAf/c/f4AAAAA/9z9/AAAAAB/3P34AAAAAD/c/fAAAAAAH9z98AAAAAAf3P3gAAAAAA/c/eAA
+ AAAAB9z9wAAAAAAH3P3AAAAAAAfc/YAAAAAAA9z9gAAAAAAD3P2AAAAAAAPc/YAAAAAAA9z9gAAAAAAD
+ 3P2AAAAAAAHc/YAAAAAAAdz9gAAAAAAD3P2AAAAAAAPc/YAAAAAAA9z9gAAAAAAD3P2AAAAAAAPc/cAA
+ AAAAA9z9wAAAAAAH3P3AAAAAAAfc/eAAAAAAD9z94AAAAAAP3P3wAAAAAB/c/fAAAAAAH9z9+AAAAAA/
+ 3P38AAAAAH/c/f4AAAAA/9z9/wAAAAH/3P3/gAAAA//c/f/wAAAH/9z9//AAAB//3P3//AAAf//c/f//
+ gAP//9z9////////3P3////////c/f///////9z9KAAAACAAAABAAAAAAQAIAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAD///8AAAAAAOqUTQB3dn4AODc7ADY1OQA+PUEAXl1hALq5vQA0MzYAV1ZZAKGf
+ owBramwAnBz/AJ0j+QCdIvEApDTsAKlN5gCpatAAtofRAMGd1ACaK88ArZC7AGVjZgCkPNAAu2LjALJY
+ 0ADBbc8ApEuxALastwCXOZsAS0lLAHNxcwCdRpkAu3G2AKRXmgDKer0AlDx8AItQcwDMjLIAqGeMANW5
+ wQA6NjcAkY2OANGVogCqo6QAzqGkAJpZWQDFwsIA6KmhAIR/fgBRRkMA0aqeALazsgBbMh8AVjksAEI7
+ OABkNh4AZDwoAKd0WgCqemMAtZqMAGFVTwDEvrsA1tTTAItNKgCPUCwAjU4rAJVULwCQUzEAklc2AJVa
+ OACVWzoAl14+AJ5pSwCgbVAAom9TAJVmTQCLYksAroBmAMu0pwDQu7AAjE4qAJxbMwCcZUIAfltFALKJ
+ cADAlnwAnoBuAL6eiwDFppQA2Ma7AM7JxgBZSD0Ao4l3AI14agDRu6wA1cO3ANfRzQBtTjcAs4hnAJl3
+ XgCHaVMATUA2AMeunAC/sacA0MjCAOni3QC9ubYA7urnAOmUTQDok00A4o9LAOqUTgDnk00A5pNOAOSS
+ TgDrl1EA4ZFOAN6QTwDajk8A7J1aANWNUQC4flAA1ZReAO2laQCxfE8AqXZMAN6cZQDkomsA7ax2AO+x
+ fgDbpnoA67OEAOGtggDsvZUAz6eFAPTKpwCskHkA9NCyAPXStQDfwakA8ta/AN3HtQDz28gA7dbDAOXZ
+ zwDaz8YA2c7FANjNxADXzMMAzMO8AMrBugDIv7gA1s3GALGrpgDJw74Ax8G8AL23sgDUzskA0szHAMvF
+ wADj3dgA7efiAMC7twDolEYA6ZZKAOmXTADqmE8Az4dIAOuaVADimFUA7KJhAM6NVQDtq24AypZpAPC5
+ hgDKn3kA8cCUAHBZRQDSro4A1LKUAH5wYwDjzLgA39TKAN7TyQDd0sgA3NHHANvQxgDaz8UA4tfNANPJ
+ wADSyL8AzcS8AMzDuwDJwLgA5dzUANrRyQDFvbYAwrqzAN7WzwDc1M0A18/IANHKxADllEEA66hkAMyU
+ XwDTnGgA4dbLANXLwQDPxr0A3dTLAOng1wDKxL4AubWxALWxrQDz7ukA7enlAM/MyQD29PIA4pA3AN+e
+ WADvtnsAjnJUAPLHmAB5aVcAqnQxAHtaMQC4lWwA3I0oANqeTQCbaSAAuoIxAMWLNQC4ikoAl3ZIAFpI
+ LQDQhRIAsnYVAMGIKgDVljIAhV8lANebPwDhrFYAiWo6AKiDSgCKbD0A47NpAPLTowB9fYYAUVFVAM7O
+ 1ABFRUcA29vgAP///wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAtbVm
+ ZmzJocxdAAAAAAAAAAAAAAAAAAAAAAAAAAAAtomJ4MRsysrLoWuinQAAAAAAAAAAAAAAAAAAAAAAibKJ
+ ZTbFvL2VlqLLa2vbnTEeAAAAAAAAAAAAAAAAALWwsGVexbu8vL2UlphdotaiMaUAAAAAAAAAAAAAAACw
+ z66JLGy/0bm5u7y9lJfS05nInqXXAAAAAAAAAAAAss+ue+QM1b+/0dG6u7y9lZfBwp/XQG0AAAAAAAAA
+ ALDQe3l3qgQN2pOTk7/Ruru8vZfSwsTY19fYAAAAAAAA0NB5eHV1tyE22ZOTv7+5ury8lZfBw8jYbdcA
+ AAAAAK6BeXd1c3BvcfoIo2yTk9HRuru9vtLBmcfY2B4AAACF0Hl4dXNwbwMDfDMLXaSkbMW5ury9l9LD
+ mjbY2AAAAH2Gd3VzbwMDA2+Kj5z6Mwzbbm6ku7yUlsHCyNec2AAAgYd1dHBvAwNvg4+4tBgHB/0I2m7F
+ u72VwNPHn5zYAACIrHNwAwMDco2PXgY5aGhoOQoG+9qkvL2XwJnH2C4AAIh1cG8DA3Krj1sraOTy6Ojo
+ 7QoFQNq8vJbSw8fXLgAAhnNvAwMDerOLOVby7u7m5u7u9e39nMW8vpfTmW3YAACGc28DA3KtjFYG9+/u
+ 5qam3ebP9wUzbLyUlsHD2NgAAIRwAwNyeq+RXgrp5s1639/Oq+7QaBjau72VwJshMwAAsW8DA6t6g5E0
+ CurmqX6z4d+t5uftGNq6vbxALP0sAACDfgMDen6Ejz8L8PR2zuH5387m+LcsNvoI+zReCx4AAISEAwOt
+ r7GMBATv+KatsbGveufzCwggNDg4VmY+AAAAAIMDdn6DhllAT+Lk+M6rq3Pm8ew+UUxVQkJCQgAAAAAA
+ sQN6sYQ+DFJiNOLr596s6PLiN2FbQkJCQkJCAAAAAAAAhIONjAwxQktcX2ggCAhoN1JhS0JCQkJCUz4A
+ AAAAAACxsYyO/GpCQlphPmc3N1lpUVpCQkJCU0RMAAAAAAAAAAAAsSwsaUREU1NHTVdXTUdTU0RERENF
+ RAAAAAAAAAAAAACKXzNbR0RERERERERERERERERDVEMAAAAAAAAAAAAAAAAAAE1bW0ZDQ0NDQ0NDQ0ZH
+ VVUwAAAAAAAAAAAAAAAAAAAATD1XSkpJSUhISElKVU2AAAAAAAAAAAAAAAAAAAAAAAAAAAA9PVdXV1dX
+ UD0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAA///////gD///gAP//gAAf/wAAH/4AAAf8AAAH+AAAAfgAAAHwAAAA4AA
+ AAOAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAADwAAAB8AAAAfgAAAH4AAAD/gA
+ AB/4AAA//wAAf/8AAf//4A////////////8oAAAAEAAAACAAAAABAAgAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAP///wAAAAAA6pRNAHd2fgA4NzsANjU5AD49QQBeXWEAurm9ADQzNgBXVlkAoZ+jAGtq
+ bACcHP8AnSP5AJ0i8QCkNOwAqU3mAKlq0AC2h9EAwZ3UAJorzwCtkLsAZWNmAKQ80AC7YuMAsljQAMFt
+ zwCkS7EAtqy3AJc5mwBLSUsAc3FzAJ1GmQC7cbYApFeaAMp6vQCUPHwAi1BzAMyMsgCoZ4wA1bnBADo2
+ NwCRjY4A0ZWiAKqjpADOoaQAmllZAMXCwgDoqaEAhH9+AFFGQwDRqp4AtrOyAFsyHwBWOSwAQjs4AGQ2
+ HgBkPCgAp3RaAKp6YwC1mowAYVVPAMS+uwDW1NMAi00qAI9QLACNTisAlVQvAJBTMQCSVzYAlVo4AJVb
+ OgCXXj4AnmlLAKBtUACib1MAlWZNAItiSwCugGYAy7SnANC7sACMTioAnFszAJxlQgB+W0UAsolwAMCW
+ fACegG4Avp6LAMWmlADYxrsAzsnGAFlIPQCjiXcAjXhqANG7rADVw7cA19HNAG1ONwCziGcAmXdeAIdp
+ UwBNQDYAx66cAL+xpwDQyMIA6eLdAL25tgDu6ucA6ZRNAOiTTQDij0sA6pROAOeTTQDmk04A5JJOAOuX
+ UQDhkU4A3pBPANqOTwDsnVoA1Y1RALh+UADVlF4A7aVpALF8TwCpdkwA3pxlAOSiawDtrHYA77F+ANum
+ egDrs4QA4a2CAOy9lQDPp4UA9MqnAKyQeQD00LIA9dK1AN/BqQDy1r8A3ce1APPbyADt1sMA5dnPANrP
+ xgDZzsUA2M3EANfMwwDMw7wAysG6AMi/uADWzcYAsaumAMnDvgDHwbwAvbeyANTOyQDSzMcAy8XAAOPd
+ 2ADt5+IAwLu3AOiURgDplkoA6ZdMAOqYTwDPh0gA65pUAOKYVQDsomEAzo1VAO2rbgDKlmkA8LmGAMqf
+ eQDxwJQAcFlFANKujgDUspQAfnBjAOPMuADf1MoA3tPJAN3SyADc0ccA29DGANrPxQDi180A08nAANLI
+ vwDNxLwAzMO7AMnAuADl3NQA2tHJAMW9tgDCurMA3tbPANzUzQDXz8gA0crEAOWUQQDrqGQAzJRfANOc
+ aADh1ssA1cvBAM/GvQDd1MsA6eDXAMrEvgC5tbEAtbGtAPPu6QDt6eUAz8zJAPb08gDikDcA355YAO+2
+ ewCOclQA8seYAHlpVwCqdDEAe1oxALiVbADcjSgA2p5NAJtpIAC6gjEAxYs1ALiKSgCXdkgAWkgtANCF
+ EgCydhUAwYgqANWWMgCFXyUA15s/AOGsVgCJajoAqINKAIpsPQDjs2kA8tOjAH19hgBRUVUAzs7UAEVF
+ RwDb2+AA////AAAAAAAAAAAAAAAAAAAAAAAAAAAAtonEystrnQAAAAAAAAAAsGXFvL2WXdYxAAAAAAAA
+ z3sMv9G6vJXBn0AAAAAA0Hl1tzaTv7m8lcHIbQAAhXl1cAN8C6RsubyXwzbYAIF1cANvj7QH/drFvcDH
+ nACIcANyjyvk6OgKQLyWw9cAhm8DrVb37qbdzwVslMHYALEDq4M06qmz3+bt2r1A/QCEA62xBO+msa/n
+ CyA4Vj4AAAOxPlI0697o4mFCQkIAAACxjPxCWj43WVFCQlNMAAAAAIozR0RERERERENDAAAAAAAAAD1K
+ SUhISk0AAAAAAAAAAAAAAAAAAAAAAAAAAAD//wAA8B8AAOAPAADABwAAgAMAAAABAAAAAQAAAAEAAAAB
+ AAAAAQAAAAEAAIADAACAAwAAwAcAAPAfAAD//wAAKAAAADAAAABgAAAAAQAgAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAHAAAADQAAABIAAAAUAAAAEgAAAAwAAAAFAAAABAAA
+ AAQAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAANAAAAGgAAACoAAAA8CwoJTx0ZFWElHxpmEw4KYAAA
+ AEwAAAA0AAAAMgAAADQAAAArAAAAIAAAABQAAAAKAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFAAAAFQAAACwKCQlPOzQtfXRjVKujinPQupp/6aqF
+ ZveOaEf6hmZL+IlzYeaBeXLBh4N/wYeDf8VwbGmwSEdFjiAfHmkAAABFAAAAKQAAABUAAAAFAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAABUAAAAzJyMeanppWrC8n4Xn3LWT/9yy
+ jf+thWL/bkst/29UPf+pmo3/1c3F/+Lc1v/j3NX/4dnT/97X0f/b1dD/19LN/8fBvPqhnJjcZGFfqCAf
+ H2kAAAA2AAAAGAAAAAUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAKCYiHmiQe2rA07GU+tuy
+ jv/VqIH/vJBr/3dZQf9dUEj/o5qT/+DY0f/n4Nn/39bP/9zUzP/a0sv/2dHK/9XOyP/Tzsn/0szG/9DK
+ xf/SzMf/087J/8C8ufqDgH3FKikodAAAADIAAAARAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABMHBgZFcWFTqNGw
+ k/jasY7/y512/8+edP+uglz/WUMz/2hnaf/LxsP/593U/93SyP/az8b/2c7F/9jNxP/WzMP/1MrC/87H
+ wf/Uy8T/08rE/9HKxP/QycP/zcfD/8rFwf/OyMT/wb26/nl3db0UFBNaAAAAHQAAAAQAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAGSUg
+ G2SrkXnZ3raT/8ygev/HlGn/0pxt/6t+V/9PPTH/eHl9/97Vzv/j18z/29DG/9zRx//b0Mb/2tDG/9nP
+ xf/YzsT/1cvC/83Gv//Oxr//zcW+/83Fvf/NxL3/zMfB/8zGwf/Jw77/xcC8/87Kx/+rqKXuPj08hwAA
+ ACkAAAAHAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAEAAAAbPjQsfMinifLWq4b/ypZr/8iNW//SlF7/rHxS/049Mf99f4P/5t3V/+LWy//d0sj/3dLI/9zR
+ x//c0cf/3NHH/9vQxv/az8b/2c/F/9fNw//UysH/0Me+/8zEvf/Jwrz/x8C5/8e/uP/Jwbv/yMS//8bC
+ v//Ev7v/wLy5/2BfXasAAAAzAAAABwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAABhHPDGF0KuJ+8+heP/JkF//zIlR/9SRWP+6h1z/VkI0/3J0ef/o4Nj/5NjN/+DV
+ y//g1Mr/39TJ/97Tyf/d0sj/3NHH/9zRx//c0cf/29DG/9rPxf/YzsT/18zD/9TKwP/Qxr7/zcS8/8nA
+ uP/BurP/w765/8fAu//Ev7v/wLu4/8TAvf9ycG+9AwMDNQAAAAUAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAED4zKnvOp4P8zJtw/8yPXf/Oi1L/0otP/8yPW/9rUT3/RUZM/8/J
+ xf/q3tL/4tfN/+LXzP/h1sz/4dXL/+DUyv/f1Mn/3tPJ/93SyP/c0cf/3NHH/9vQxv/az8b/2M7E/9bM
+ w//UysH/0ce//87EvP/Hv7j/wLq1/763sP/Cu7b/w766/766tv/EwL3/cG9tuwAAACoAAAACAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGJR4YXsSbePXMmGr/zZJg/9COV//Si1D/3ZFS/59n
+ OP9IQT7/V1li/9nU0v/y59z/49fM/+TYzv/j2M3/4tfN/+HWzP/g1cv/39TK/97Tyf/d0sj/3NHH/9zR
+ x//b0Mf/2s/G/9nOxf/WzMP/1MrB/9HHv//OxLz/yMC4/8C6tP+7ta//vrex/8G8uP+9ubX/wb27/1ta
+ WaUAAAAYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJBwY0poJj38+XaP/PlWT/0pJb/9KL
+ T//YjU//4ZJR/7t4P/9cTUP/bnF9/4iHjv/a1tL/9evh/+XZzv/k2c7/5NjO/+PYzf/i18z/4dbL/+DV
+ y//f1Mr/3tPJ/93SyP/c0cf/3NHH/9rQxv/ZzsX/18zD/9TKwf/Rx77/zcS8/8nAuP/BurT/urSv/7q0
+ rv+/urb/vLm2/7q2tP81NTR3AAAABwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA9tVUCp0plo/86V
+ ZP/VmGT/1IxP/9mOT//dj0//4JFO/+eUTv+uc0L/c25x/29yfv9YWF3/ube1//jv5v/o3NH/5dnO/+TZ
+ zv/k2M7/4tfN/+LWzP/g1cv/39TK/97Tyf/d0sj/3NHH/9zRx//a0Mb/2c7E/9fMw//UysH/0Me+/8zD
+ u//Iv7f/wbmz/7q0r/+4sq3/vbi0/767uP+fnZvrDQ0NOwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACYe
+ FlfFj2H8zZFd/9mgcP/VjVH/2Y5O/96QT//hkU7/45JO/+aTT//slUz/s3dF/3hydf9scH3/TExR/5eV
+ lf/z6+T/7eHW/+XZzv/l2s//5NnO/+PYzf/i18z/4dXL/+DUyv/e08n/3dLI/9zRx//c0cf/2tDG/9nO
+ xP/WzML/08nA/8/Gvf/Lwrr/xr62/8C4sv+3sq7/trGr/7u3s//Bvrv/ZGNhrAAAAAwAAAAAAAAAAAAA
+ AAAAAAAAAAAAEIlkRcLTkFj/2aJ0/9iUW//ZjU3/3pBP/+GRTv/kkk7/5pNO/+eTTf/plE3/8JZM/8R/
+ Rv+CdXH/dHqI/1FSWP91dHb/493Y//Ln3P/m2c//5drP/+TZzv/j2M3/4tbM/+HWy//g1Mr/3tPJ/93S
+ yP/c0cf/29HH/9rPxv/YzsT/1cvC/9LIwP/Oxbz/ysG5/8W8tf+9trD/trCs/7Wvq/+8uLX/sK2r+hoa
+ GUoAAAAAAAAAAAAAAAAAAAAAKSAYUcuOWf7VmGX/3aJx/9mNTP/ekE7/4pFO/+SSTv/mk07/55NN/+mT
+ Tf/plE3/6pRN//GXTP/YiUf/lHlo/3p/jf9cXmf/XFxf/8nEwf/27OL/6NzS/+bb0f/l2tD/5NjO/+LW
+ y//g1cr/39TK/97Tyf/c0cf/3NHH/9vQxv/az8X/183E/9XLwf/Rx7//zcS7/8i/uP/CurP/urSv/7Su
+ qf+1r6v/w7+8/2ZkY6oAAAAFAAAAAAAAAAAAAAACeFk+ptuXXf/eqHr/3JVa/96PTf/hkU7/5JJO/+aT
+ Tv/ok03/6ZNN/+mUTf/qlE3/6pRN/+qUTf/vl03/6ZFH/7F/Wv+CfoX/Z2p0/05PU/+op6b/+vby//Tv
+ 6v/v6+b/7ujj/+rj3v/m3dX/4dfM/97TyP/e0sj/3NHH/9zRx//b0Mb/2c7F/9fMw//UycD/0Ma9/8vC
+ uv/Fvbb/v7ex/7eyrv+xq6b/ubWx/6ajofEMDAwsAAAAAAAAAAAFAwEevIle6NybZf/hqXj/3Y5M/+GR
+ Tv/kkk7/5pNO/+iTTf/pk03/6ZRN/+qUTf/qlE3/6pRN/+qUTf/qk0v/7JNJ//OpbP/YuaH/npqe/3h6
+ hP9OTlT/hoaH/+rn5f/x7en/9PHt//r28v/28e7/7enk/+be1//f1Mr/3dHH/9zRx//c0cf/2s/G/9jO
+ xP/Wy8L/0si//87EvP/IwLj/w7u0/7u1r/+0r6r/r6ql/7+7uP8+PDxuAAAAAAAAAAAuIhdQ3Z5p/+Cm
+ df/hnmX/4I9L/+SSTv/mk07/55NN/+mTTf/plE3/6pRN/+qUTf/qlE3/6pRN/+qSSf/rl1L/772T//fc
+ x//94cr/z7Sc/4yIjP+FhpH/XV1k/1lZXf9paGv/dXR2/5mXmP/QzMr/9fHt//Xx7v/q5eD/4NbM/9zR
+ xv/c0cf/29DH/9rPxf/XzcP/1MrB/9DHvv/Lwrr/xr62/7+3sf+4s67/sKql/7q2sv9zcW+vAAAAAQAA
+ AABkSzaF6KRr/+Wuf//gk1P/45FN/+WSTv/nk03/6ZNN/+mUTf/qlE3/6pRN/+qUTf/qlE3/6pJJ/+ua
+ WP/xyKf/++PP/+LEq/+Yfmj/aVtU/1xbYP9TUln/R0dN/zc2O/81NDn/ODc8/zk5Pf9HR0z/f31//9jV
+ 0v/49PH/7Ofj/+DWzf/c0Mb/3NHH/9vQxv/ZzsX/1szC/9LIwP/OxLz/ycC4/8K6s/+7tbD/tK6q/7Gs
+ qP+Wk5HdBAQEFAAAAACQbEyw6qZt/+etff/ij0v/5ZJO/+eTTf/ok03/6ZRN/+qUTf/qlE3/6pRN/+qU
+ Tf/qk0v/65hU//HIpv/748//yauR/3JeUf9NS1H/OTtC/y4uM/8rKzL/LS0z/zAwNf8xMDT/Li81/y8w
+ Nv80NDj/Nzc8/1JSVf+8ubj/+PTw/+zm4v/e1Mr/3NHG/9vQxv/az8X/183D/9TKwf/Qxr7/y8K6/8W9
+ tf++t7H/t7Kt/7Cqpf+mop/2GRkZMS0tLAmugFnM6qly/+ipdP/jj0r/5pNO/+iTTf/plE3/6ZRN/+qU
+ Tf/qlE3/6pRN/+qUTf/rlU3/77uR//vj0P/FqI//ZVZN/0NFTf89Njb/S0A7/1FFO/9ZSTT/X0ww/19M
+ MP9iTC3/YUop/0U8Mf80MjX/MDA1/zY2O/9HR0z/vru6//fz8P/o4dz/3NHG/9zRx//b0Mb/2M7E/9XL
+ wv/SyL//zcS8/8i/t//BubP/ubSv/7Osp/+uqaX/Ly4uSzo2NBbAi1/d66p1/+ika//lkEr/6JNN/+mT
+ Tf/plE3/6pRN/+qUTf/qlE3/6pRN/+qVT//tp23/+N3H/9zBqv9tWUz/Q0VN/0s+N/9oUUH/blMx/4lg
+ IP+kbhj/s3YT/7d4E/+wdRb/r3QV/5JlHP9cSSv/QTkx/zAwNf82Njv/Wlpc/+Hd2f/y7er/4djP/9vQ
+ xv/b0Mb/2s/F/9fNw//TycD/z8a9/8rBuf/Du7T/u7Ww/7Wvqf+1r6v/Ojk4Xzw6OBzEjV7l7Kt0/+ig
+ ZP/mkUr/6JNN/+mUTf/qlE3/6pRN/+qUTf/qlE3/65ZQ/+yaVv/xw53/9+HO/5J2X/9MSk//RTs4/3JX
+ Qf93Vyn/n2sW/8B9D//Ngwv/0oYM/9SHDv/Vhw3/0YYM/8uCC/+kcBv/cVcu/0k+L/8xMDX/ODg9/5SR
+ kf/28+//6OLc/9zRxv/c0cf/2s/G/9jOxP/Vy8H/0ce+/8zDu//Gvbb/vbex/7myrf+4s7D/Ozo4Zzw7
+ OhvGjV3m7apz/+meYf/nkUr/6ZRN/+qUTf/qlE3/6pRN/+qUTf/qlU7/7JpX/+2kaP/32sH/1ruk/2ZU
+ SP89PkX/Z04+/39dLf+lbhX/yYEN/9SHDv/Zihv/3o0o/+COLv/gjS3/3Ywk/9iJFv/Thgr/snwk/3th
+ OP9EOi7/MjI4/1taXP/h3Nn/8Ovn/97Uyv/c0cb/29DG/9nOxf/WzML/0si//83EvP/Iv7f/v7mz/7u2
+ sv+4sq7/PTs5ZD07OhLHkGHe7qpx/+qfYf/okkr/6ZRN/+qUTf/qlE3/6pRN/+qUTf/rmFT/7J1d/++x
+ fv/75NH/rY92/1NMTP8+Oj3/dFs+/51qGv/IgQ3/1ogQ/92NJ//lkT3/6pZL/+uZUf/rmFD/6ZRH/+OP
+ N//bix3/1IcM/7CEPf9vWDf/ODQy/0JCR/++urb/9fHu/+HY0P/b0Mb/29DG/9rPxf/XzMP/08nA/8/F
+ vf/JwLj/w7y1/8G5s/+7ta//PDs5VTQ0NQW9i2HN8alu/+ufYf/okkr/6pRN/+qUTf/qlE3/6pRN/+uW
+ UP/snVv/7aFj//C7j//449H/knVd/0tKT/9EPj3/gmAr/8eBIv/ViBD/3Iwk/+eTQ//snFf/7aVk/+2q
+ av/tqWn/7aNg/+uYUf/kkDn/2okW/8yMJP+bekn/UUMy/zk6P/+loZ7/9/Pv/+Tb0//c0Mb/3NHH/9rP
+ xv/XzcT/1MrB/9HHvv/SycD/x8C5/4mFgf+fmpX/MS8uOwAAAACogmOx9apt/+yiZf/pkkr/6pRN/+qU
+ Tf/qlE3/6pRN/+uaVv/toWL/7qVp//LBmP/1387/hGlU/0hJUf9KQDb/mmsh/9iRL//Zihr/45A4/+yb
+ Vf/tqWn/77Z6/++8g//vu4H/7rJ0/+2kYv/qlkz/340q/9WLGP+3j1D/cFk2/zw6O/+bmJf/9vLv/+Tc
+ 1f/c0Mb/3NHH/9vQxv/c0cf/3dPI/9TLw/+rpqT/X15e/0FBQP+SjYnvGxoaHAAAAACDaVOD+a5w/+yl
+ af/pkkn/6pRN/+qUTf/qlE3/65ZQ/+ydXP/upGj/76lv//LCm//14M//gmlV/01OWP9RRDL/pnEd/9ua
+ Ov/cjiX/55JD/+2iX//us3b/8cON//LPnP/yzJn/8L6F/+6tbv/snFb/4482/9iNG//JnVf/hmUy/0Q/
+ Ov+in53/9/Pw/+fe1v/i18v/5NnO/97Uy//Kwrz/o5+f/3d2e/9UVVv/Pz9B/1NSUf+Mh4PMBgUFAgAA
+ AABKOixJ+bF2/+2mbP/qk0v/6pRN/+qUTf/qlE3/65hU/+2gYf/up23/76x1//LAl//45dT/iXFe/1tc
+ Zv9XRzL/qHAW/9yhQ//fkzH/6JNF/+2lY//vt3v/8cmV//PZrP/z1aX/8MKM/+6wcv/snlr/5I84/9uS
+ J//SpVv/jWUl/09MSv/Avbn/+vbz/93W0f/Dvbr/paGj/4OCh/9jZGv/S05V/01QV/9UVVv/PkBB/2Zk
+ Yv9zb2yRAAAAAAAAAAATDQgS46Ry7PGpbf/rmFL/6pRM/+qUTf/qlU7/7JxZ/+2jZv/vqnL/8LB8//K8
+ j//85tT/gXl1/4OGlf9oWUf/nmcO/9iePf/in0T/5pA+/+2iX//us3b/8MOM//LOnP/yy5j/8L2F/+6t
+ bv/snFb/4o0y/96bPP/LkTP/kG89/3d5g/+joqT/iImQ/2xvdv9aXWb/TlJa/0lKUP9HREf/ST48/1Y/
+ Nv9uSzv/dltN/4eDgP9FQkBEAAAAAAAAAAAAAAAAqHxXpfqwc//snl3/6pJK/+qUTf/rllH/7J5d/+6m
+ av/vrXb/8LOB//e9jv/gxa7/enuE/6Oltv9lX1v/kGEV/82KHP/lrVn/5JI9/+uZU//tqWj/77V5/++8
+ gv/vuoD/7rF0/+2kYv/qlkv/4I8v/9mSJ/++gR7/ZF5V/0xLUv9GQUL/RD09/0k7OP9NOTH/Uzgs/1w5
+ KP9oPSf/dkQq/4dQM/+TVjT/mGlO/5SQjNwQEA8IAAAAAAAAAAAAAAAATDgmQvqydv/to2b/6pNL/+qU
+ Tf/rmFP/7Z9g/+6obv/wr3n/8raF//nAkP+Yhnn/nKCv/4lxa/9GPT7/b19G/6dwF//Xli3/6bBf/+ul
+ X//snFf/7aRi/+2qaf/tqWj/7qNf/+6aUP/kkDf/2okV/9WKEf+Fbkr/STUx/2hALP93UDz/dko0/3xL
+ Mf+CTzT/iFI1/4xSM/+OUjH/jlAu/4xNKv+KSCP/m3pn/2VlY3gAAAAAAAAAAAAAAAAAAAAABwQCAcqS
+ Y8X3rW//65lV/+qTS//snFr/7qVp/+6nbP/wsHz/+8CP/7aSdv+Qkp7/trfD/7+mmf9jPSv/R0NH/3Nm
+ UP+dbCf/yoUk/+OfRP/so1T/7ZtQ/+6aUP/umk7/5pJE/9CEMf/Uhhj/1ZAe/4t0Tf9HMSv/kGdS/9O+
+ sv/CpZP/kVc2/49SMP+OTy3/jE0q/4pLKf+KSyn/i0wq/4tMKf+PUC7/nIyC6RscHBQAAAAAAAAAAAAA
+ AAAAAAAAAAAAAFc+KUT9s3b/7aBh/+qRSf/xuIj/9cuo//G5i//8zKX/y6eK/4mHjP+3u8n/rJaP/82y
+ ov+5nY7/XDcl/0VAQv9rY1j/mnJF/7p6Mv/KgzP/0og4/9KEN//HejL/oWYr/3daM/93Y0H/ZF1T/0Uw
+ K/+DWkT/1L6x/864qv+VX0D/h0Yk/4pMKf+KTCr/ikwq/4tNKv+LTSr/i00q/4lJJP+hcFT/X11abgAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACsfFSg/K9v/+uZVf/zwJb/9tO1//nYvf/xx6X/fG9n/7S4
+ xf+9ucD/kVg4/5diQ//SvK//vqOU/2tDMP9DMy//S0xQ/2dfWP9/Z1H/jGpL/45qSf+DZkv/bWBT/1hX
+ Vf9HP0D/Ty0h/5BpVP/TvbD/0Lqt/51tUP+HRiP/i00q/4tNKv+LTSr/i00q/4tNKv+LTSr/i0wp/5NS
+ Lf+SemvGDA0OBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAfFxAT4aFs3fSlY//xuoz/9tO2///W
+ tf+zj3P/dHV7/9TX4/+vkof/iUch/4dHI/+XY0T/yrGi/9C7r/+Xc2D/YT8v/0c0Lv9BOTr/Qz5A/0Q+
+ P/9FOjn/RzIs/1QxIf93TTj/s5SE/9nGvP/KsKH/m2lL/4dHIv+LTSr/i00q/4tNKv+LTSr/jE0q/4xN
+ Kv+MTir/jUsm/51rTuY1MzEoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAASDYnOPav
+ dPfzrnT/9s6u//vPqv93Y1T/jZCX/9za4P+dak//iUgj/4xNKv+ISCT/jlQx/7ONd//UvrH/zreq/6+R
+ gf+UcV//hmFP/4VfTP+LZFD/nnpo/72hkv/Wwrf/076x/7SQev+RVzX/iEcj/4tNKv+MTSr/jE0q/4xN
+ Kv+MTir/jE4q/4xOK/+MTSr/m1s3/0c1K0wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAG9WQlj9uYH+9reE/+i7lf9US0f/i46W/9nOzP+rfWL/iksm/4xOKv+MTir/iksn/4hH
+ I/+UXDv/rYVr/8Wnlf/Quav/1L6y/9XAtP/VwLP/0bqs/8Snlv+uhW3/ll8//4hIJP+KSib/jE4q/4xO
+ Kv+MTir/jE4q/4xOK/+MTiv/j08s/41OK/+YUy3/ZkAqjQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB0YE9h/8OP/tuleP9LRkX/V1ph/7ypof+0h27/h0Ug/4xN
+ Kf+NTiv/jE4r/4xOKv+KSyf/iEgj/4pMKP+RVzT/lmA//5lkRP+WYED/kVg1/4tNKf+ISCP/ikom/4xO
+ Kv+MTiv/jE4r/41OK/+NTiv/jU4r/41OK/+WVS7/mlcv/5lVLv9uPSGiCAQBAgAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAd2dZWPTGoPNfT0H/ODo+/6OE
+ dP+odFb/qXpf/5FTMf+LSib/jU4r/41OK/+NTiv/jU4r/4xNKv+MTCj/i0on/4pKJv+LSif/i0wo/4xN
+ Kv+NTiv/jU4r/41OK/+NTiv/jU4r/41OK/+MTir/jk8r/5hXMP+eWjH/nVoz/2A2H5EAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAE9J
+ RDF+alqfWEIx0pxqTf2fZ0j/yaua/76ZhP+ZYD//jEwo/41OKv+NTir/jU4q/41OK/+NTiv/jU4r/41O
+ K/+NTiv/jU4r/41OK/+NTir/jU4q/41OKv+NTir/jU4q/45PK/+SVDD/nV43/6RjO/+aXTr0TC4dagAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAExIQBZtvVduobk3/rH1i/8CciP+ziXH/kFIv/5FUMf+RUzD/kFIu/5BR
+ Lv+PUS3/j1Et/49QLf+PUC3/j1Et/49RLf+QUS7/kFIv/5FTMP+SVTL/llo3/55jQP+nbEf/qm1J/4NT
+ OMAsHBMxAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADIjGzSDWUCwqXJT/614Wf+odVj/oWxO/51l
+ Rv+aYUD/mF49/5ddPP+XXDv/l1w7/5ZcOv+WXDr/llw7/5ddPP+YXz7/m2JC/59oSP+lb0//rnZV/7F4
+ Vv+YZknWTjQlYQYFAwIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANCQbOXNQ
+ PJukdFjntYNm/7WEZ/+wgGT/rHtf/6h3Wv+mdFf/pXJV/6VxVP+mclX/p3RY/6p4XP+vfWD/tIFj/7aC
+ ZP+uel33iV9Hu0s0J1oRDAkJAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAJAwATOCMYT2NDMZGEXEXElmtS5qN1XPmmeV//qnxi/6t9Yv+leF7/pXdc/Ztu
+ VO+NYkrTcU05pUUtH2cXDAYmAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAq6akD760ryPCt7E21sa9P9vK
+ wEPBtrA5wrexK7GrpxakoaACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP//wAf//9z9//4AAH//
+ 3P3/+AAAH//c/f/gAAAH/9z9/8AAAAP/3P3/gAAAAP/c/f4AAAAAf9z9/AAAAAA/3P38AAAAAB/c/fgA
+ AAAAD9z98AAAAAAP3P3wAAAAAAfc/eAAAAAAB9z94AAAAAAD3P3AAAAAAAPc/cAAAAAAAdz9gAAAAAAB
+ 3P2AAAAAAAHc/YAAAAAAANz9gAAAAAAA3P2AAAAAAADc/QAAAAAAANz9AAAAAAAA3P0AAAAAAADc/QAA
+ AAAAANz9AAAAAAAA3P0AAAAAAADc/YAAAAAAANz9gAAAAAAA3P2AAAAAAAHc/YAAAAAAAdz9wAAAAAAB
+ 3P3AAAAAAAPc/cAAAAAAA9z94AAAAAAH3P3wAAAAAAfc/fAAAAAAD9z9+AAAAAAf3P38AAAAAD/c/f4A
+ AAAAP9z9/wAAAAD/3P3/gAAAAf/c/f/gAAAD/9z9//AAAAf/3P3//AAAH//c/f//AAD//9z9///wB///
+ 3P3////////c/SgAAAAgAAAAQAAAAAEAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAAFgAAACMAAAAiAAAAEwAA
+ AAkAAAAJAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYAAAAmIx8bWlpMQI57ZVG2dFhBzGdO
+ OsxcUEWvWFVTllZUUZY4NjV4FBMTTAAAACIAAAAGAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIEBAUwTkM7h6KIcdTTq4j9tI1t/4dp
+ UP+mkoD/1svB/+Xd1f/k3Nb/39nT/9bRzP/AurX2j4uIzkRDQocFBQU2AAAABQAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAROjIscayRed3bsYz/1qR6/4Vj
+ SP93b2r/ysS+/+Xd1f/e1Mz/2c/H/9bNxf/RysT/1MzF/9TNxv/W0cz/0MvH/6Gem+NAPz6DAAAAHAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBIG9eT6fUrYr/1KB0/8yU
+ ZP95WkH/gX19/9/Xz//h1sv/29DG/9vQxv/az8X/1szD/9DIwP/Oxr//zMS9/8vEvv/LxL//zsnF/8rG
+ w/94dnTBCwsLOAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBCKHcFvA2qqB/82Q
+ XP/SkVr/gl9C/358ff/o3tb/49fM/97Tyf/d0sj/3NHH/9zRx//b0Mb/2c7F/9XLwv/Qx7//zMO7/8e+
+ t//Evrn/x8K9/8vHw/+VkpDeFBQURAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEUgGhSvNik
+ eP/Njln/1o1Q/6FwR/9MS03/2tTP/+re0v/i18z/4dbM/+DVy//e08n/3dLI/9zRx//b0Mf/2s/F/9fN
+ w//TycD/zcS8/8S8tv++uLL/wbu2/8jEwP+XlJLiDg4ONAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVtI
+ N5XWoHH/0ZNe/9OMUP/gklD/k2I5/1hdZ/+ysLL/8Obd/+nc0f/j2M3/4tfN/+HWy//f1Mr/3tPI/9zR
+ x//c0cf/2s/F/9fMw//TycD/zcS8/8S8tf+7ta//vbez/8fDwP9+fHvJAQEBFAAAAAAAAAAAAAAAAAAA
+ AAAjGxVLxZBj/NaZZ//Wj1P/245O/+KST//fjUn/lHNb/2FndP+GhYj/5d3W/+7i1v/k2M7/49jN/+LW
+ zP/g1cv/3tPJ/93Sx//c0cf/2s/F/9fMw//SyL//zMO7/8S8tf+6tK7/urWx/8PAvf9IR0aGAAAAAAAA
+ AAAAAAAAAAAACIpjQcTdn2v/2ZVd/9yOTf/hkU7/5ZJO/+uVTv/mkEj/onte/2Jmcv9sbnT/0MrE//Pn
+ 3P/l2c7/49fN/+LWy//g1cr/3tPJ/93Sx//c0cf/2c/F/9bMwv/Rx77/ysG6/8G6s/+3saz/vbi0/6aj
+ ofANDQ0oAAAAAAAAAAAlGxJH0ZNf/92gbP/cjk3/4pFO/+WTTv/ok03/6ZRN/+yWTf/ulEn/vYZa/3Zw
+ c/9cX2f/s66r//Tr4v/t5Nv/6N/W/+TZz//g1Mr/3tLI/9zRx//b0Mb/2c7F/9TKwf/Pxb3/x7+3/722
+ sP+0rqr/wb26/1BPTocAAAAAAAAAAHBQNJvnqHL/35he/+GPTP/lk07/6JNN/+mUTf/qlE3/6pRN/+uT
+ S//xk0X/3aV4/5+anP9hYmv/mJia/+vo5v/x7en/9/Pu//Lr5f/j2tH/3dHH/9zRx//b0Mb/183E/9LJ
+ wP/Mw7v/xLu0/7iyrf+4s67/kY+N1wICAgwdHR0NrX1U1uipdf/hklD/5ZJO/+iTTf/plE3/6pRN/+qU
+ Tf/qk0r/6pVP//TCmf/52sD/v6aR/358gv9bXGT/VVVZ/2RjZv+Ih4j/y8jG//fy7v/o4Nn/3NHG/9zR
+ x//az8X/1svC/9DGvv/Iv7j/vrex/7Suqv+tqab8IB8fOz01LjLRmGj156Rt/+OQS//nk03/6ZRN/+qU
+ Tf/qlE3/6pNL/+qVTv/2yaT/48q1/4NxZf9FQkX/Njc//zAyOv8sLTT/Kywz/yorM/88PEH/kI+P//Ds
+ 6f/o4Nn/29DG/9vQxv/YzcT/08nA/8zDu//Du7T/uLKt/7Wvq/9DQkFrXk0/UuGkcf/nn2T/5pFK/+mU
+ Tf/qlE3/6pRN/+qUTf/qkkr/87uN/+XNuP9vYFj/Pzs//01BOf9gSy//dFUo/3dYJ/92ViT/UEEt/zAv
+ Mv8tLjT/ioiJ//Xw7P/i2M//29DG/9nPxf/Vy8L/z8a9/8e+t/+8trD/ubOu/1xaWY1tWEdk56dx/+ic
+ Xv/okkr/6ZRN/+qUTf/qlE3/6pRM/+2hY//32L//j3tt/0E8P/9mTzr/i2Ii/7h4D//Ngwz/0YUO/86E
+ DP+0dhL/b1Qq/zg0MP83Nz3/wL27//Hq5P/c0cb/29DG/9fNw//RyL//ysG5/7+4sv+9uLP/ZWJgnW9a
+ SWPppm//6Ztb/+mSS//qlE3/6pRN/+qUTf/rl1L/9LyN/9nAq/9TSkf/Vkc+/5JmIv/HgAv/24sX/+KO
+ Lf/kkDf/4o8v/92LF//Fgxj/eV42/zAuLv95eHn/8+7p/9/Vy//b0Mb/2c7E/9TKwf/Mw7v/xLy1/8W+
+ uf9nY2GaaFZIT+mmbv/qm1r/6ZNL/+qUTf/qlEz/65dR/+2eXv/5zaj/tp+M/0E+Q/9sVDP/w34X/9uL
+ GP/nk0L/7Z9c/+2mZf/toV7/6JRF/96MGv+7hzL/V0k2/1VVWP/m4t7/5NrS/9vQxv/Zz8X/1szD/9XL
+ wv/Gvrf/pJ6a/11aV4NLRD4t46Rv9uydW//qk0v/6pRN/+qUTf/snFr/7qVo//vTsv+mkID/Pz5D/4Zh
+ KP/akSb/4o4w/+2hXv/vt3z/8MKL/++5f//to2L/5I8z/9SSK/+GakD/U1BO/+Hd2v/p39b/4dbL/+LX
+ zP/WzMT/sKup/2NiY/9jYmD/RUJAWiYmJQjKk2XX8qNi/+qTSv/qlEz/65dR/+2hY//vqnD//NOz/6uY
+ iv9MSU3/kGUf/96cN//mkj3/7qlp//HFj//z2Kr/8ciT/+6rbf/mkT3/3Zo5/5x2Of9saGP/7Ojm/9zV
+ 0P+8t7T/lpWY/2hqcf9QUlr/P0BD/3Fua/cmJCMkAAAAAJJqSJf7rm3/6pRM/+qUTP/smlf/7qZq/++u
+ eP/9zqf/qaCc/3d5hf+LYBv/3Z86/+eXQv/tomD/8L2E//HLl//wv4f/7qdn/+aSPf/dmDD/l3Q8/25y
+ e/97fIH/Xl5j/05KTv9JPz7/UDw1/2pHNv+DX0z/dnJuwgYGBQEAAAAAPiwdPfmwdP/rl1L/6pRM/+yb
+ Wf/uqG//9baB/+Kyiv+Ylp3/enB1/2RSNf+/hCP/56ZL/+6iWv/upmX/769w//Gqaf/wm07/5pAh/8WI
+ Iv9fTDz/X0Y9/2RFNv9qQi3/dUYt/39JK/+ITCz/jkwn/59vVP9NTEtiAAAAAAAAAAADAQABwotdwvel
+ Yv/qllH/7612//Gwev/xuo3/o5KJ/7Cwu/+wlIX/UT44/2pbQ/+2fzL/4JhA/+qZSP/qlUf/2Ig9/7l5
+ LP+0gS3/ZUw0/4trXv/Os6P/mWJC/45OK/+OTyz/jU4q/4xNKf+PTSf/jnNk3A4QEQoAAAAAAAAAAAAA
+ AABDMCA49qpr/O+kZf/20LH//tSx/7GXhP+or73/pYN0/7aOdf+yloj/WUI7/1VKRP9/ZEb/mm9E/5xu
+ Qv98X0L/U0tB/0w6Nf+MbF//1L2v/6R0Wf+HRiL/ikwp/4tNKv+LTSr/i0sm/51kRP9EPjpRAAAAAAAA
+ AAAAAAAAAAAAAAAAAACGYECA/7N0//jOrP/mv5//hX99/8fBxv+PUzL/iEgj/7KKcf/DqJn/jHFl/19M
+ R/9TQ0D/U0I9/1xFPP97XE7/tZiK/861pv+gb1P/h0cj/4tNKv+LTSr/jE0q/4xNKv+WUy7/a008kAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAUEBAGwgVqp/8mT/7yYfP92eoD/zbmy/49RLf+KSib/iEcj/5pk
+ Rf+6lX//w6WT/76hkf++oZH/xKeX/8epl/+xiHD/kFU0/4hHI/+MTSr/jE4q/4xNKv+NTyv/lVIs/35K
+ LcgLCQgGAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA0MDAe/lXKtwJZ1/0dKUf+zmIv/mmA+/4pJ
+ Jf+MTSr/ikom/4lII/+PUi//l18+/5ljQ/+UWzr/jE4q/4hHI/+LTCj/jU4r/41OK/+MTSr/k1It/6Fb
+ Mv+ASCfPGA0HHAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA8ODgN9a1yCV0g81ppp
+ Tv+5j3f/q31i/45OKv+NTSn/jU4q/4xNKf+LSyf/i0om/4tLJ/+MTSn/jU4q/41OKv+NTSr/jk8r/5pa
+ NP+nZDv/ckQosREKBhQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAARDgwIhVtCwbR/YP++lHz/nWVF/5JVM/+SVDH/kVMw/5FTL/+QUy//kVMv/5FTMP+SVTL/lVk2/59j
+ QP+sb0v/nGVF500xIW0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAGAgAJRSweY4NYQMendVj9rHha/6hzVP+jbk//oWpM/6BqS/+ibE3/pnBR/6t1
+ Vv+qdVb/kmRJ2Fg6KX0RCgUZAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEtAOS51X1JplXhnmamHc7i0j3rItZB7yauI
+ dL2bfGmhf2ZXdVRGPjstKikHAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAA//AP//+AAf/+AAB//AAAP/gAAB/wAAAP4AAAB8AAAAPAAAADgAAAAYAAAAGAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAAAAgAAAAYAAAAHAAAAD4AAAB+AAAAfwAAAP+AAAH/4A
+ AH//AAD//+AD//////8oAAAAGAAAADAAAAABACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAgMDIRcTED8QCgRGAAAALAAAACAAAAAVAAAAAQAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAES0n
+ Ilp5ZVOolHZc2opsU/Kgi3j2qqCX5aijn9uSj4vMYl9dnSUkI1gAAAAUAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAjHxtMknpmxterhP+rg2P/j4B0/8rAt//j29P/4tnR/9zU
+ zf/c1c//3NXP/8rFwP+Kh4TMJyYmWwAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAktA
+ Nn3Hn3343qRy/5lwTv+Kgn7/39bP/+LXzP/b0Mb/2s/F/9XLwv/Qx8D/zcW+/8zFv//Szcj/wb26/1VU
+ U5gAAAANAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAU0Q3h9OieP/Xk1n/o3FH/3x1cv/p4Nj/49fN/9/U
+ yv/e08n/3dHH/9vQx//ZzsT/08nB/83Du//Evbf/xcC6/8rFwv9mZGOsAAAACgAAAAAAAAAAAAAAAAAA
+ AAA2KyFhz5xw/9SSWf/dj03/f1s+/4GGkf/q4dj/69/T/+LXzP/h1sz/39TK/93SyP/c0cf/2c/F/9XK
+ wf/NxLz/wbqz/7+5tP/Hw7//UE9OjgAAAAAAAAAAAAAAAAkHBR2vgFnp3Jtk/9mOTv/kkk7/14pL/4Nv
+ Zf90eYP/08zF//Dk2P/k2M7/4tbM/+DUyv/d0sj/3NHH/9nOxf/UysH/zMO7/7+4sv+9t7P/trKv/R4e
+ HUEAAAAAAAAAAFg+KIXhomz/3JJU/+KRTf/mk07/7pZN/+OQS/+UdmL/ZWhx/7eyr//y5tv/6d7U/+TY
+ zv/f08n/3dLH/9zRx//YzsT/0si//8nAuf+7ta//wby4/3d1c7cAAAACFhUVD618U9vloGf/4ZBM/+eT
+ Tv/plE3/6pRN/+6US//uk0f/wp2C/3Z3f/+ioKL/6+bi//Hs5//z7OT/49nP/9zQxv/b0Mb/18zD/8/G
+ vf/EvLX/uLKt/6yopfgYGBgwRDcsRNmebf3jmFj/5pJM/+mUTf/qlE3/6pNL/+uVTv/4xJj/3b+m/4R7
+ ef9PUl7/TE5V/2Jjaf+joaL/6+fj/+jf1v/b0Mb/2s/F/9TKwf/Lwbr/vbaw/7izr/9IR0ZzdFtFdemo
+ cv/lk1D/6ZNN/+qUTf/qlE3/6pNK//fDmP+7qJj/T0hJ/zw3OP9GPDD/SDwr/zwzK/8nKDD/aWls/+Xh
+ 3v/k2tH/28/F/9fNw//Pxr3/w7y1/7u1sP9raGaijm5Tj+2nbf/nk0z/6pRN/+qUTf/qkkr/8650/9S8
+ p/9QSEf/XUk1/5ZnHf+9exD/xX8R/7V3Ef9sUSf/Kikr/4SEhv/x6uX/3NHH/9nOxf/TycD/yMC4/8C6
+ tP96d3W4knBVju+maf/pk0z/6pRN/+qUTP/sl1L/+Mif/41+df9NQTr/pW8a/9iJEv/mkTH/6ZQ9/+WR
+ K//QiBj/clgw/0JCRv/a1tP/49nQ/9rPxf/Vy8L/z8a9/8rDvP99eXW1gmdSc/Gmaf/qlEz/6pRN/+uW
+ UP/vomP/8sqq/2pgXv9pUTH/1Ykb/+eTOv/vqWv/8LR5/+6lZf/nkS7/vIYw/05GPP/Bv77/6+HY/+HW
+ yv/f1Mr/xLy3/4eEgf9dWleYVUY7QOula/7rlU7/6pRM/+ybWP/wqm//8s2u/25nZ/9+Xir/4Zcw/+ua
+ Uf/xwIn/89Sl//C5gP/qlkT/1ZU2/3RhRP/Jycv/3NbS/7Wxr/+Ghon/WVpg/1RTU/9BPz1gHhwZCs2S
+ YNrynFX/6pRM/+2gYf/zsHj/68Oh/4WGkv+BZDb/3Zky/+2eUv/wtnv/8ceS//Gydv/rlj//z48r/21g
+ UP9ua3D/X1dX/1NEQf9XPTL/dUkz/4ZxZfAaGxsbAAAAAH5aPH/9qWT/65ZR/+6mav/2t4L/uqGR/6CZ
+ n/9eSz7/nnQx/+WeRv/xolX/8qJZ/+STRv/WjCX/h2Ar/4NqYf+KYEr/fkYo/4hLKv+MTCn/mFcy/2la
+ UJoAAAAAAAAAABcQCxTemF7l9q91//vQrP/Mq4//o6Gq/7KNev+kiHr/W0tE/3pdPP+kcz//pW88/3RW
+ Nv9eSTb/kHZt/8amk/+TVzX/i0sn/4xNKv+NTCf/lGNH8B0dHSAAAAAAAAAAAAAAAABSOiVM/biA//fN
+ q/+akYz/t6Wg/4ZDHf+lc1b/tJSD/4dya/9uXln/bVtU/4FpYP+ukoX/vJeC/5BUMv+JSib/i00q/4xN
+ Kv+XVjH/RDInWQAAAAAAAAAAAAAAAAAAAAAAAAAAd1pCbu22iP9xbnD/tJeI/4tJI/+IRiH/klY0/6l4
+ W/+ziHD/tIx0/7GFbP+eaEn/iUol/4tLJ/+MTSr/kVEs/5xXL/9YMx2MAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAGZVRmBjVEjWoXVc/7CBZv+RVDH/i0om/4lII/+JRyL/iUgj/4lHIv+KSSX/jE0p/41O
+ Kv+aWTP/oV83/lEvG38AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMCQcIck03qLaH
+ bP+td1j/ml06/5ZZNv+TVjP/k1Yz/5RYNf+ZXDr/omZD/6hsSf+HVzvHLx0URAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwdFjlpTDuOkWpTyqJ1XOmoeV/1qHle9qN1
+ W+yWbFPRc1I/mzkpH0gGBQQCAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAANfSzxnk3Ncr5d3YLNrU0B3IxsUEAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAA/wD/QfwAP0H4AA9B4AAHQeAAA0HAAANBgAABQYAAAEEAAABBAAAAQQAA
+ AEEAAABBAAAAQQAAAEEAAABBAAAAQYAAAUGAAAFBwAADQeAAB0HwAA9B+AAfQf4AP0H/wf9BKAAAABAA
+ AAAgAAAAAQAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFBEPKjYr
+ IGY8LyOBNjIuZywrKlIJCQklAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPDw4ld2FOoKKA
+ Y+2lj37/z8G0/9rRyf/QysT/s66p6WxqaKMSEhIuAAAAAAAAAAAAAAAAAAAAAAAAAAAnIRxFto1p58KP
+ Y/+ik4f/3dXO/+HXzf/b0Mb/1czD/9PLw//Vzsj/r6uo7zAvLloAAAAAAAAAAAAAAAAXEw8uu4xk7+GV
+ VP9/ZFD/xsbH/+/j1//h1cv/3tPJ/9zRx//XzMP/zMO7/8nCvP+3s7D7JSUlRwAAAAAEBggDiWREvOSc
+ X//kkUv/y4ZP/4N5df+5trX/7uLX/+XZzv/f08j/3NHH/9fNw//Kwbn/xb+5/5KPjdgFBQUPOy8kRNaX
+ Yv/kk0//6JRN//CWSv/ejk3/moh//6uqrP/n4dv/7+ff/+Xa0P/az8X/1MrB/8W9tf+8t7L/Pj08ZIVm
+ S5LqoGL/55JL/+qUTP/tlk7/8ruM/56Mgf9GSVT/SElQ/29xd//Tz8z/5tvS/9jOxP/Oxb3/wru1/3Vy
+ cLGvg1+67ZxZ/+qTS//rkkj/87SA/42Be/9WQy3/kGEX/51nE/9eQxn/T1BU/93X0//f1Mn/1MrB/8jB
+ uv+RjInStIZgue+bVv/qk0r/8Z1Y/9Wxlf9ZTEL/unkX/+yYNf/xnkj/3o8m/2ZOKP+hoKL/7OLY/9/U
+ yf/Nxb3/iYWBz5ZyVJDzn1j/6pRM//Wqbf/Hq5j/b1k3/+OTLv/xs3j/88mY//GhUf+tei3/np2c/9nU
+ 0f+opKP/cnBx/05MSqZNPC5A7p9d/+yWT//3sHX/xq6g/3doU//UkDP/97Fs//e9gP/xnkP/o3Ux/3Jm
+ ZP9sVEv/ZUEw/4JZQ/82MzFRCQkLAa52R7b/uX7/4riW/6ycmP+UeW3/e2JE/7J6QP+ucjz/h2E1/5l/
+ bf+ebVL/iEci/5VQKf96UzzEBggJBQAAAAAkGA4j6bOE6buqnv+efG3/llg0/557av+IcWb/h3Bk/51/
+ cv+kc1j/ikom/5JQKv+OUC7yIBcSKQAAAAAAAAAAAAAAAD0vJDR6aFrPp3xk/5haN/+NSyb/mFs5/5le
+ Pf+RUS7/jEok/5tZMv+QUzDpLBkORQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABlU5KYaTZkzjll49/5Zb
+ Ov+WWjj/l108/41ZOulfOiWaDQUAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAjYiFFbeo
+ n0zOuq5wz7qucrqqoVGTjYocAAAAAAAAAAAAAAAAAAAAAAAAAAD4H6xB4AesQcADrEGAAaxBAACsQQAA
+ rEEAAKxBAACsQQAArEEAAKxBAACsQQAArEGAAaxBwAOsQeAHrEH4H6xB
+
+
+
\ No newline at end of file
diff --git a/lib/CefSharp.Dom.WinForms.Example/CefSharp.Dom.WinForms.Example.csproj b/lib/CefSharp.Dom.WinForms.Example/CefSharp.Dom.WinForms.Example.csproj
new file mode 100644
index 000000000..c4749b378
--- /dev/null
+++ b/lib/CefSharp.Dom.WinForms.Example/CefSharp.Dom.WinForms.Example.csproj
@@ -0,0 +1,26 @@
+
+
+
+ WinExe
+ netcoreapp3.1
+ true
+ app.manifest
+ $(NETCoreSdkRuntimeIdentifier)
+ false
+
+
+
+
+
+
+
+
+
+ PreserveNewest
+
+
+
+
+
+
+
diff --git a/lib/CefSharp.Dom.WinForms.Example/Controls/ControlExtensions.cs b/lib/CefSharp.Dom.WinForms.Example/Controls/ControlExtensions.cs
new file mode 100644
index 000000000..a826ef5b4
--- /dev/null
+++ b/lib/CefSharp.Dom.WinForms.Example/Controls/ControlExtensions.cs
@@ -0,0 +1,37 @@
+// Copyright © 2022 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;
+using System.Windows.Forms;
+
+namespace CefSharp.Dom.WinForms.Example.Controls
+{
+ public static class ControlExtensions
+ {
+ ///
+ /// Executes the Action asynchronously on the UI thread, does not block execution on the calling thread.
+ ///
+ /// the control for which the update is required
+ /// action to be performed on the control
+ public static void InvokeOnUiThreadIfRequired(this Control control, Action action)
+ {
+ //If you are planning on using a similar function in your own code then please be sure to
+ //have a quick read over https://stackoverflow.com/questions/1874728/avoid-calling-invoke-when-the-control-is-disposed
+ //No action
+ if (control.Disposing || control.IsDisposed || !control.IsHandleCreated)
+ {
+ return;
+ }
+
+ if (control.InvokeRequired)
+ {
+ control.BeginInvoke(action);
+ }
+ else
+ {
+ action.Invoke();
+ }
+ }
+ }
+}
diff --git a/lib/CefSharp.Dom.WinForms.Example/Program.cs b/lib/CefSharp.Dom.WinForms.Example/Program.cs
new file mode 100644
index 000000000..b3471d1c3
--- /dev/null
+++ b/lib/CefSharp.Dom.WinForms.Example/Program.cs
@@ -0,0 +1,46 @@
+// Copyright © 2022 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 CefSharp.WinForms;
+using System;
+using System.IO;
+using System.Windows.Forms;
+
+namespace CefSharp.Dom.WinForms.Example
+{
+ public static class Program
+ {
+ [STAThread]
+ public static int Main(string[] args)
+ {
+ Application.SetHighDpiMode(HighDpiMode.PerMonitorV2);
+
+ var settings = new CefSettings()
+ {
+ //By default CefSharp will use an in-memory cache, you need to specify a Cache Folder to persist data
+ CachePath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "CefSharp\\Cache")
+ };
+
+ //Example of setting a command line argument
+ //Enables WebRTC
+ // - CEF Doesn't currently support permissions on a per browser basis see https://bitbucket.org/chromiumembedded/cef/issues/2582/allow-run-time-handling-of-media-access
+ // - CEF Doesn't currently support displaying a UI for media access permissions
+ //
+ //NOTE: WebRTC Device Id's aren't persisted as they are in Chrome see https://bitbucket.org/chromiumembedded/cef/issues/2064/persist-webrtc-deviceids-across-restart
+ settings.CefCommandLineArgs.Add("enable-media-stream");
+ //https://peter.sh/experiments/chromium-command-line-switches/#use-fake-ui-for-media-stream
+ settings.CefCommandLineArgs.Add("use-fake-ui-for-media-stream");
+ //For screen sharing add (see https://bitbucket.org/chromiumembedded/cef/issues/2582/allow-run-time-handling-of-media-access#comment-58677180)
+ settings.CefCommandLineArgs.Add("enable-usermedia-screen-capturing");
+
+ //Perform dependency check to make sure all relevant resources are in our output directory.
+ Cef.Initialize(settings, performDependencyCheck: true, browserProcessHandler: null);
+
+ var browser = new BrowserForm();
+ Application.Run(browser);
+
+ return 0;
+ }
+ }
+}
diff --git a/lib/CefSharp.Dom.WinForms.Example/Properties/Resources.Designer.cs b/lib/CefSharp.Dom.WinForms.Example/Properties/Resources.Designer.cs
new file mode 100644
index 000000000..321a615da
--- /dev/null
+++ b/lib/CefSharp.Dom.WinForms.Example/Properties/Resources.Designer.cs
@@ -0,0 +1,110 @@
+//------------------------------------------------------------------------------
+//
+// This code was generated by a tool.
+// Runtime Version:4.0.30319.18034
+//
+// Changes to this file may cause incorrect behavior and will be lost if
+// the code is regenerated.
+//
+//------------------------------------------------------------------------------
+
+namespace CefSharp.Dom.WinForms.Example.Properties {
+ ///
+ /// A strongly-typed resource class, for looking up localized strings, etc.
+ ///
+ // This class was auto-generated by the StronglyTypedResourceBuilder
+ // class via a tool like ResGen or Visual Studio.
+ // To add or remove a member, edit your .ResX file then rerun ResGen
+ // with the /str option, or rebuild your VS project.
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+ internal class Resources {
+
+ private static global::System.Resources.ResourceManager resourceMan;
+
+ private static global::System.Globalization.CultureInfo resourceCulture;
+
+ [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
+ internal Resources() {
+ }
+
+ ///
+ /// Returns the cached ResourceManager instance used by this class.
+ ///
+ [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+ internal static global::System.Resources.ResourceManager ResourceManager {
+ get {
+ if (object.ReferenceEquals(resourceMan, null)) {
+ global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("CefSharp.Dom.WinForms.Example.Properties.Resources", typeof(Resources).Assembly);
+ resourceMan = temp;
+ }
+ return resourceMan;
+ }
+ }
+
+ ///
+ /// Overrides the current thread's CurrentUICulture property for all
+ /// resource lookups using this strongly typed resource class.
+ ///
+ [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+ internal static global::System.Globalization.CultureInfo Culture {
+ get {
+ return resourceCulture;
+ }
+ set {
+ resourceCulture = value;
+ }
+ }
+
+ ///
+ /// Looks up a localized resource of type System.Drawing.Bitmap.
+ ///
+ internal static System.Drawing.Bitmap chromium256 {
+ get {
+ object obj = ResourceManager.GetObject("chromium256", resourceCulture);
+ return ((System.Drawing.Bitmap)(obj));
+ }
+ }
+
+ ///
+ /// Looks up a localized resource of type System.Drawing.Bitmap.
+ ///
+ internal static System.Drawing.Bitmap nav_left_green {
+ get {
+ object obj = ResourceManager.GetObject("nav_left_green", resourceCulture);
+ return ((System.Drawing.Bitmap)(obj));
+ }
+ }
+
+ ///
+ /// Looks up a localized resource of type System.Drawing.Bitmap.
+ ///
+ internal static System.Drawing.Bitmap nav_plain_green {
+ get {
+ object obj = ResourceManager.GetObject("nav_plain_green", resourceCulture);
+ return ((System.Drawing.Bitmap)(obj));
+ }
+ }
+
+ ///
+ /// Looks up a localized resource of type System.Drawing.Bitmap.
+ ///
+ internal static System.Drawing.Bitmap nav_plain_red {
+ get {
+ object obj = ResourceManager.GetObject("nav_plain_red", resourceCulture);
+ return ((System.Drawing.Bitmap)(obj));
+ }
+ }
+
+ ///
+ /// Looks up a localized resource of type System.Drawing.Bitmap.
+ ///
+ internal static System.Drawing.Bitmap nav_right_green {
+ get {
+ object obj = ResourceManager.GetObject("nav_right_green", resourceCulture);
+ return ((System.Drawing.Bitmap)(obj));
+ }
+ }
+ }
+}
diff --git a/lib/CefSharp.Dom.WinForms.Example/Properties/Resources.resx b/lib/CefSharp.Dom.WinForms.Example/Properties/Resources.resx
new file mode 100644
index 000000000..641637ff5
--- /dev/null
+++ b/lib/CefSharp.Dom.WinForms.Example/Properties/Resources.resx
@@ -0,0 +1,136 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+
+ ..\Resources\nav_right_green.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
+
+
+ ..\Resources\nav_left_green.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
+
+
+ ..\Resources\nav_plain_red.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
+
+
+ ..\Resources\nav_plain_green.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
+
+
+ ..\Resources\chromium-256.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
+
+
\ No newline at end of file
diff --git a/lib/CefSharp.Dom.WinForms.Example/Resources/chromium-256.png b/lib/CefSharp.Dom.WinForms.Example/Resources/chromium-256.png
new file mode 100644
index 000000000..a392e00fe
Binary files /dev/null and b/lib/CefSharp.Dom.WinForms.Example/Resources/chromium-256.png differ
diff --git a/lib/CefSharp.Dom.WinForms.Example/Resources/nav_left_green.png b/lib/CefSharp.Dom.WinForms.Example/Resources/nav_left_green.png
new file mode 100644
index 000000000..0433aada7
Binary files /dev/null and b/lib/CefSharp.Dom.WinForms.Example/Resources/nav_left_green.png differ
diff --git a/lib/CefSharp.Dom.WinForms.Example/Resources/nav_plain_green.png b/lib/CefSharp.Dom.WinForms.Example/Resources/nav_plain_green.png
new file mode 100644
index 000000000..95b73f0ee
Binary files /dev/null and b/lib/CefSharp.Dom.WinForms.Example/Resources/nav_plain_green.png differ
diff --git a/lib/CefSharp.Dom.WinForms.Example/Resources/nav_plain_red.png b/lib/CefSharp.Dom.WinForms.Example/Resources/nav_plain_red.png
new file mode 100644
index 000000000..e160e0e71
Binary files /dev/null and b/lib/CefSharp.Dom.WinForms.Example/Resources/nav_plain_red.png differ
diff --git a/lib/CefSharp.Dom.WinForms.Example/Resources/nav_right_green.png b/lib/CefSharp.Dom.WinForms.Example/Resources/nav_right_green.png
new file mode 100644
index 000000000..410585caa
Binary files /dev/null and b/lib/CefSharp.Dom.WinForms.Example/Resources/nav_right_green.png differ
diff --git a/lib/CefSharp.Dom.WinForms.Example/app.config b/lib/CefSharp.Dom.WinForms.Example/app.config
new file mode 100644
index 000000000..de8289320
--- /dev/null
+++ b/lib/CefSharp.Dom.WinForms.Example/app.config
@@ -0,0 +1,3 @@
+
+
+
diff --git a/lib/CefSharp.Dom.WinForms.Example/app.manifest b/lib/CefSharp.Dom.WinForms.Example/app.manifest
new file mode 100644
index 000000000..219a5c562
--- /dev/null
+++ b/lib/CefSharp.Dom.WinForms.Example/app.manifest
@@ -0,0 +1,52 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/lib/CefSharp.Dom.WinForms.Example/crash_reporter.cfg b/lib/CefSharp.Dom.WinForms.Example/crash_reporter.cfg
new file mode 100644
index 000000000..26d468ab1
--- /dev/null
+++ b/lib/CefSharp.Dom.WinForms.Example/crash_reporter.cfg
@@ -0,0 +1,12 @@
+# Crash reporting is configured using an INI-style config file named
+# "crash_reporter.cfg". This file must be placed next to
+# the main application executable.
+# Comments start with a hash character and must be on their own line.
+# See https://bitbucket.org/chromiumembedded/cef/wiki/CrashReporting.md
+# for further details
+
+[Config]
+ProductName=CefSharp.Dom.WinForms.Example
+ProductVersion=1.0.0
+AppName=CefSharp.Dom
+ExternalHandler=CefSharp.BrowserSubprocess.exe
diff --git a/lib/CefSharp.Dom.Wpf.Example/App.xaml b/lib/CefSharp.Dom.Wpf.Example/App.xaml
new file mode 100644
index 000000000..cde88db5f
--- /dev/null
+++ b/lib/CefSharp.Dom.Wpf.Example/App.xaml
@@ -0,0 +1,9 @@
+
+
+
+
+
diff --git a/lib/CefSharp.Dom.Wpf.Example/App.xaml.cs b/lib/CefSharp.Dom.Wpf.Example/App.xaml.cs
new file mode 100644
index 000000000..08c178f1f
--- /dev/null
+++ b/lib/CefSharp.Dom.Wpf.Example/App.xaml.cs
@@ -0,0 +1,37 @@
+using System;
+using System.IO;
+using System.Windows;
+using CefSharp.Wpf;
+
+namespace CefSharp.Dom.Wpf.Example
+{
+ ///
+ /// Interaction logic for App.xaml
+ ///
+ public partial class App : Application
+ {
+ public App()
+ {
+ var settings = new CefSettings()
+ {
+ //By default CefSharp will use an in-memory cache, you need to specify a Cache Folder to persist data
+ CachePath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "CefSharp\\Cache")
+ };
+
+ //Example of setting a command line argument
+ //Enables WebRTC
+ // - CEF Doesn't currently support permissions on a per browser basis see https://bitbucket.org/chromiumembedded/cef/issues/2582/allow-run-time-handling-of-media-access
+ // - CEF Doesn't currently support displaying a UI for media access permissions
+ //
+ //NOTE: WebRTC Device Id's aren't persisted as they are in Chrome see https://bitbucket.org/chromiumembedded/cef/issues/2064/persist-webrtc-deviceids-across-restart
+ settings.CefCommandLineArgs.Add("enable-media-stream");
+ //https://peter.sh/experiments/chromium-command-line-switches/#use-fake-ui-for-media-stream
+ settings.CefCommandLineArgs.Add("use-fake-ui-for-media-stream");
+ //For screen sharing add (see https://bitbucket.org/chromiumembedded/cef/issues/2582/allow-run-time-handling-of-media-access#comment-58677180)
+ settings.CefCommandLineArgs.Add("enable-usermedia-screen-capturing");
+
+ //Perform dependency check to make sure all relevant resources are in our output directory.
+ Cef.Initialize(settings, performDependencyCheck: true, browserProcessHandler: null);
+ }
+ }
+}
diff --git a/lib/CefSharp.Dom.Wpf.Example/AssemblyInfo.cs b/lib/CefSharp.Dom.Wpf.Example/AssemblyInfo.cs
new file mode 100644
index 000000000..8b5504ecf
--- /dev/null
+++ b/lib/CefSharp.Dom.Wpf.Example/AssemblyInfo.cs
@@ -0,0 +1,10 @@
+using System.Windows;
+
+[assembly: ThemeInfo(
+ ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located
+ //(used if a resource is not found in the page,
+ // or application resource dictionaries)
+ ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located
+ //(used if a resource is not found in the page,
+ // app, or any theme specific resource dictionaries)
+)]
diff --git a/lib/CefSharp.Dom.Wpf.Example/CefSharp.Dom.Wpf.Example.csproj b/lib/CefSharp.Dom.Wpf.Example/CefSharp.Dom.Wpf.Example.csproj
new file mode 100644
index 000000000..83ff5fcc8
--- /dev/null
+++ b/lib/CefSharp.Dom.Wpf.Example/CefSharp.Dom.Wpf.Example.csproj
@@ -0,0 +1,24 @@
+
+
+
+ WinExe
+ netcoreapp3.1
+ true
+ $(NETCoreSdkRuntimeIdentifier)
+ false
+ app.manifest
+
+
+
+
+
+
+
+
+
+
+ PreserveNewest
+
+
+
+
diff --git a/lib/CefSharp.Dom.Wpf.Example/MainWindow.xaml b/lib/CefSharp.Dom.Wpf.Example/MainWindow.xaml
new file mode 100644
index 000000000..0f234237f
--- /dev/null
+++ b/lib/CefSharp.Dom.Wpf.Example/MainWindow.xaml
@@ -0,0 +1,57 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/lib/CefSharp.Dom.Wpf.Example/MainWindow.xaml.cs b/lib/CefSharp.Dom.Wpf.Example/MainWindow.xaml.cs
new file mode 100644
index 000000000..77f52d3a1
--- /dev/null
+++ b/lib/CefSharp.Dom.Wpf.Example/MainWindow.xaml.cs
@@ -0,0 +1,68 @@
+using System.Diagnostics;
+using System.Windows;
+
+namespace CefSharp.Dom.Wpf.Example
+{
+ ///
+ /// Interaction logic for MainWindow.xaml
+ ///
+ public partial class MainWindow : System.Windows.Window
+ {
+ public MainWindow()
+ {
+ InitializeComponent();
+
+ Browser.RegisterResourceHandler("https://cefsharp.test/textarea.html", System.IO.File.OpenRead("textarea.html"));
+ }
+
+ private async void ExecuteTestButtonClick(object sender, RoutedEventArgs e)
+ {
+ await Browser.WaitForInitialLoadAsync();
+
+ var devToolsContext = await Browser.CreateDevToolsContextAsync(ignoreHTTPSerrors:true);
+
+ await devToolsContext.GoToAsync("https://cefsharp.test/textarea.html");
+
+ await devToolsContext.EvaluateExpressionAsync(@"{
+ window.addEventListener('keydown', event => window.keyLocation = event.location, true);
+ }");
+ var textarea = await devToolsContext.QuerySelectorAsync("textarea");
+
+ await textarea.PressAsync("Digit5");
+
+ var actual = await devToolsContext.EvaluateExpressionAsync("keyLocation");
+
+ Debug.Assert(0 == actual);
+
+ await textarea.PressAsync("ControlLeft");
+
+ actual = await devToolsContext.EvaluateExpressionAsync("keyLocation");
+
+ Debug.Assert(1 == actual);
+
+ await textarea.PressAsync("ControlRight");
+
+ actual = await devToolsContext.EvaluateExpressionAsync("keyLocation");
+
+ Debug.Assert(2 == actual);
+
+ await textarea.PressAsync("NumpadSubtract");
+
+ actual = await devToolsContext.EvaluateExpressionAsync("keyLocation");
+
+ Debug.Assert(3 == actual);
+
+ if(actual == 3)
+ {
+ await textarea.SetValueAsync("Testing Complete");
+ }
+
+ await devToolsContext.DisposeAsync();
+ }
+
+ private void ShowDevToolsClick(object sender, RoutedEventArgs e)
+ {
+ Browser.ShowDevTools();
+ }
+ }
+}
diff --git a/lib/CefSharp.Dom.Wpf.Example/TextBoxBindingUpdateOnEnterBehaviour.cs b/lib/CefSharp.Dom.Wpf.Example/TextBoxBindingUpdateOnEnterBehaviour.cs
new file mode 100644
index 000000000..dd81181b4
--- /dev/null
+++ b/lib/CefSharp.Dom.Wpf.Example/TextBoxBindingUpdateOnEnterBehaviour.cs
@@ -0,0 +1,28 @@
+using System.Windows.Controls;
+using System.Windows.Input;
+using Microsoft.Xaml.Behaviors;
+
+namespace CefSharp.Dom.Wpf.Example
+{
+ public class TextBoxBindingUpdateOnEnterBehaviour : Behavior
+ {
+ protected override void OnAttached()
+ {
+ AssociatedObject.KeyDown += OnTextBoxKeyDown;
+ }
+
+ protected override void OnDetaching()
+ {
+ AssociatedObject.KeyDown -= OnTextBoxKeyDown;
+ }
+
+ private void OnTextBoxKeyDown(object sender, KeyEventArgs e)
+ {
+ if (e.Key == Key.Enter)
+ {
+ var txtBox = sender as TextBox;
+ txtBox.GetBindingExpression(TextBox.TextProperty).UpdateSource();
+ }
+ }
+ }
+}
diff --git a/lib/CefSharp.Dom.Wpf.Example/app.manifest b/lib/CefSharp.Dom.Wpf.Example/app.manifest
new file mode 100644
index 000000000..669820c40
--- /dev/null
+++ b/lib/CefSharp.Dom.Wpf.Example/app.manifest
@@ -0,0 +1,77 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ PerMonitorV2
+ true/PM
+ true
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/lib/CefSharp.Dom.Wpf.Example/textarea.html b/lib/CefSharp.Dom.Wpf.Example/textarea.html
new file mode 100644
index 000000000..ad34a6991
--- /dev/null
+++ b/lib/CefSharp.Dom.Wpf.Example/textarea.html
@@ -0,0 +1,14 @@
+
+
+
+ Textarea test
+
+
+ Text Area Test
+
+
+
+ Checkbox
+
+
+
diff --git a/lib/PuppeteerSharp.ruleset b/lib/CefSharp.Dom.ruleset
similarity index 97%
rename from lib/PuppeteerSharp.ruleset
rename to lib/CefSharp.Dom.ruleset
index 415e56789..2c884470f 100644
--- a/lib/PuppeteerSharp.ruleset
+++ b/lib/CefSharp.Dom.ruleset
@@ -1,4 +1,4 @@
-
+
@@ -34,6 +34,7 @@
+
diff --git a/lib/CefSharp.Dom.sln b/lib/CefSharp.Dom.sln
new file mode 100644
index 000000000..8111cee40
--- /dev/null
+++ b/lib/CefSharp.Dom.sln
@@ -0,0 +1,134 @@
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 17
+VisualStudioVersion = 17.5.33502.453
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CefSharp.Dom", "PuppeteerSharp\CefSharp.Dom.csproj", "{19B9B1ED-AF6C-4DAF-8B73-401570111F88}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CefSharp.Dom.Tests", "PuppeteerSharp.Tests\CefSharp.Dom.Tests.csproj", "{1682289E-5ED3-405F-8ABC-01A3ED58CBC6}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CefSharp.Dom.TestServer", "PuppeteerSharp.TestServer\CefSharp.Dom.TestServer.csproj", "{0CC393AB-10C2-4CDB-8353-78924D3DD5D3}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CefSharp.Dom.DevicesFetcher", "PuppeteerSharp.DevicesFetcher\CefSharp.Dom.DevicesFetcher.csproj", "{A500694A-3649-4474-BC71-C835FA19B865}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{5993B99D-AC7B-4D6F-832C-6784D7EFE9B3}"
+ ProjectSection(SolutionItems) = preProject
+ .editorconfig = .editorconfig
+ CefSharp.Dom.ruleset = CefSharp.Dom.ruleset
+ ..\Directory.Build.props = ..\Directory.Build.props
+ ..\README.md = ..\README.md
+ Common\SignAssembly.props = Common\SignAssembly.props
+ EndProjectSection
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CefSharp.Dom.Xunit", "PuppeteerSharp.Xunit\CefSharp.Dom.Xunit.csproj", "{EE53767C-D321-4BCF-B372-57949F38AB40}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CefSharp.Dom.Wpf.Example", "CefSharp.Dom.Wpf.Example\CefSharp.Dom.Wpf.Example.csproj", "{D9163132-1A78-40A8-9E39-F2C74FB29353}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CefSharp.Dom.WinForms.Example", "CefSharp.Dom.WinForms.Example\CefSharp.Dom.WinForms.Example.csproj", "{1D1D63D1-5257-4AA0-A284-7EF4574878CB}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Debug|x64 = Debug|x64
+ Debug|x86 = Debug|x86
+ Release|Any CPU = Release|Any CPU
+ Release|x64 = Release|x64
+ Release|x86 = Release|x86
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {19B9B1ED-AF6C-4DAF-8B73-401570111F88}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {19B9B1ED-AF6C-4DAF-8B73-401570111F88}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {19B9B1ED-AF6C-4DAF-8B73-401570111F88}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {19B9B1ED-AF6C-4DAF-8B73-401570111F88}.Debug|x64.Build.0 = Debug|Any CPU
+ {19B9B1ED-AF6C-4DAF-8B73-401570111F88}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {19B9B1ED-AF6C-4DAF-8B73-401570111F88}.Debug|x86.Build.0 = Debug|Any CPU
+ {19B9B1ED-AF6C-4DAF-8B73-401570111F88}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {19B9B1ED-AF6C-4DAF-8B73-401570111F88}.Release|Any CPU.Build.0 = Release|Any CPU
+ {19B9B1ED-AF6C-4DAF-8B73-401570111F88}.Release|x64.ActiveCfg = Release|Any CPU
+ {19B9B1ED-AF6C-4DAF-8B73-401570111F88}.Release|x64.Build.0 = Release|Any CPU
+ {19B9B1ED-AF6C-4DAF-8B73-401570111F88}.Release|x86.ActiveCfg = Release|Any CPU
+ {19B9B1ED-AF6C-4DAF-8B73-401570111F88}.Release|x86.Build.0 = Release|Any CPU
+ {1682289E-5ED3-405F-8ABC-01A3ED58CBC6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {1682289E-5ED3-405F-8ABC-01A3ED58CBC6}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {1682289E-5ED3-405F-8ABC-01A3ED58CBC6}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {1682289E-5ED3-405F-8ABC-01A3ED58CBC6}.Debug|x64.Build.0 = Debug|Any CPU
+ {1682289E-5ED3-405F-8ABC-01A3ED58CBC6}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {1682289E-5ED3-405F-8ABC-01A3ED58CBC6}.Debug|x86.Build.0 = Debug|Any CPU
+ {1682289E-5ED3-405F-8ABC-01A3ED58CBC6}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {1682289E-5ED3-405F-8ABC-01A3ED58CBC6}.Release|Any CPU.Build.0 = Release|Any CPU
+ {1682289E-5ED3-405F-8ABC-01A3ED58CBC6}.Release|x64.ActiveCfg = Release|Any CPU
+ {1682289E-5ED3-405F-8ABC-01A3ED58CBC6}.Release|x64.Build.0 = Release|Any CPU
+ {1682289E-5ED3-405F-8ABC-01A3ED58CBC6}.Release|x86.ActiveCfg = Release|Any CPU
+ {1682289E-5ED3-405F-8ABC-01A3ED58CBC6}.Release|x86.Build.0 = Release|Any CPU
+ {0CC393AB-10C2-4CDB-8353-78924D3DD5D3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {0CC393AB-10C2-4CDB-8353-78924D3DD5D3}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {0CC393AB-10C2-4CDB-8353-78924D3DD5D3}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {0CC393AB-10C2-4CDB-8353-78924D3DD5D3}.Debug|x64.Build.0 = Debug|Any CPU
+ {0CC393AB-10C2-4CDB-8353-78924D3DD5D3}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {0CC393AB-10C2-4CDB-8353-78924D3DD5D3}.Debug|x86.Build.0 = Debug|Any CPU
+ {0CC393AB-10C2-4CDB-8353-78924D3DD5D3}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {0CC393AB-10C2-4CDB-8353-78924D3DD5D3}.Release|Any CPU.Build.0 = Release|Any CPU
+ {0CC393AB-10C2-4CDB-8353-78924D3DD5D3}.Release|x64.ActiveCfg = Release|Any CPU
+ {0CC393AB-10C2-4CDB-8353-78924D3DD5D3}.Release|x64.Build.0 = Release|Any CPU
+ {0CC393AB-10C2-4CDB-8353-78924D3DD5D3}.Release|x86.ActiveCfg = Release|Any CPU
+ {0CC393AB-10C2-4CDB-8353-78924D3DD5D3}.Release|x86.Build.0 = Release|Any CPU
+ {A500694A-3649-4474-BC71-C835FA19B865}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {A500694A-3649-4474-BC71-C835FA19B865}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {A500694A-3649-4474-BC71-C835FA19B865}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {A500694A-3649-4474-BC71-C835FA19B865}.Debug|x64.Build.0 = Debug|Any CPU
+ {A500694A-3649-4474-BC71-C835FA19B865}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {A500694A-3649-4474-BC71-C835FA19B865}.Debug|x86.Build.0 = Debug|Any CPU
+ {A500694A-3649-4474-BC71-C835FA19B865}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {A500694A-3649-4474-BC71-C835FA19B865}.Release|Any CPU.Build.0 = Release|Any CPU
+ {A500694A-3649-4474-BC71-C835FA19B865}.Release|x64.ActiveCfg = Release|Any CPU
+ {A500694A-3649-4474-BC71-C835FA19B865}.Release|x64.Build.0 = Release|Any CPU
+ {A500694A-3649-4474-BC71-C835FA19B865}.Release|x86.ActiveCfg = Release|Any CPU
+ {A500694A-3649-4474-BC71-C835FA19B865}.Release|x86.Build.0 = Release|Any CPU
+ {EE53767C-D321-4BCF-B372-57949F38AB40}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {EE53767C-D321-4BCF-B372-57949F38AB40}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {EE53767C-D321-4BCF-B372-57949F38AB40}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {EE53767C-D321-4BCF-B372-57949F38AB40}.Debug|x64.Build.0 = Debug|Any CPU
+ {EE53767C-D321-4BCF-B372-57949F38AB40}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {EE53767C-D321-4BCF-B372-57949F38AB40}.Debug|x86.Build.0 = Debug|Any CPU
+ {EE53767C-D321-4BCF-B372-57949F38AB40}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {EE53767C-D321-4BCF-B372-57949F38AB40}.Release|Any CPU.Build.0 = Release|Any CPU
+ {EE53767C-D321-4BCF-B372-57949F38AB40}.Release|x64.ActiveCfg = Release|Any CPU
+ {EE53767C-D321-4BCF-B372-57949F38AB40}.Release|x64.Build.0 = Release|Any CPU
+ {EE53767C-D321-4BCF-B372-57949F38AB40}.Release|x86.ActiveCfg = Release|Any CPU
+ {EE53767C-D321-4BCF-B372-57949F38AB40}.Release|x86.Build.0 = Release|Any CPU
+ {D9163132-1A78-40A8-9E39-F2C74FB29353}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {D9163132-1A78-40A8-9E39-F2C74FB29353}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {D9163132-1A78-40A8-9E39-F2C74FB29353}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {D9163132-1A78-40A8-9E39-F2C74FB29353}.Debug|x64.Build.0 = Debug|Any CPU
+ {D9163132-1A78-40A8-9E39-F2C74FB29353}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {D9163132-1A78-40A8-9E39-F2C74FB29353}.Debug|x86.Build.0 = Debug|Any CPU
+ {D9163132-1A78-40A8-9E39-F2C74FB29353}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {D9163132-1A78-40A8-9E39-F2C74FB29353}.Release|Any CPU.Build.0 = Release|Any CPU
+ {D9163132-1A78-40A8-9E39-F2C74FB29353}.Release|x64.ActiveCfg = Release|Any CPU
+ {D9163132-1A78-40A8-9E39-F2C74FB29353}.Release|x64.Build.0 = Release|Any CPU
+ {D9163132-1A78-40A8-9E39-F2C74FB29353}.Release|x86.ActiveCfg = Release|Any CPU
+ {D9163132-1A78-40A8-9E39-F2C74FB29353}.Release|x86.Build.0 = Release|Any CPU
+ {1D1D63D1-5257-4AA0-A284-7EF4574878CB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {1D1D63D1-5257-4AA0-A284-7EF4574878CB}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {1D1D63D1-5257-4AA0-A284-7EF4574878CB}.Debug|x64.ActiveCfg = Debug|x64
+ {1D1D63D1-5257-4AA0-A284-7EF4574878CB}.Debug|x64.Build.0 = Debug|x64
+ {1D1D63D1-5257-4AA0-A284-7EF4574878CB}.Debug|x86.ActiveCfg = Debug|x86
+ {1D1D63D1-5257-4AA0-A284-7EF4574878CB}.Debug|x86.Build.0 = Debug|x86
+ {1D1D63D1-5257-4AA0-A284-7EF4574878CB}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {1D1D63D1-5257-4AA0-A284-7EF4574878CB}.Release|Any CPU.Build.0 = Release|Any CPU
+ {1D1D63D1-5257-4AA0-A284-7EF4574878CB}.Release|x64.ActiveCfg = Release|x64
+ {1D1D63D1-5257-4AA0-A284-7EF4574878CB}.Release|x64.Build.0 = Release|x64
+ {1D1D63D1-5257-4AA0-A284-7EF4574878CB}.Release|x86.ActiveCfg = Release|x86
+ {1D1D63D1-5257-4AA0-A284-7EF4574878CB}.Release|x86.Build.0 = Release|x86
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {F9F7978B-89C0-4A54-8D80-A1E93E401D4C}
+ EndGlobalSection
+ GlobalSection(MonoDevelopProperties) = preSolution
+ Policies = $0
+ $0.DotNetNamingPolicy = $1
+ $1.DirectoryNamespaceAssociation = PrefixedHierarchical
+ EndGlobalSection
+EndGlobal
diff --git a/lib/Common/SignAssembly.props b/lib/Common/SignAssembly.props
index 2e74be07a..a1cfe4153 100644
--- a/lib/Common/SignAssembly.props
+++ b/lib/Common/SignAssembly.props
@@ -1,13 +1,12 @@
- 0024000004800000940000000602000000240000525341310004000001000100059a04ca5ca77c9b4eb2addd1afe3f8464b20ee6aefe73b8c23c0e6ca278d1a378b33382e7e18d4aa8300dd22d81f146e528d88368f73a288e5b8157da9710fe6f9fa9911fb786193f983408c5ebae0b1ba5d1d00111af2816f5db55871db03d7536f4a7a6c5152d630c1e1886b1a0fb68ba5e7f64a7f24ac372090889be2ffb
true
- ..\keys\keypair.snk
+ ..\keys\CefSharp.snk
false
-
- keypair.snk
+
+ CefSharp.snk
diff --git a/lib/NuGet.config b/lib/NuGet.config
new file mode 100644
index 000000000..631795137
--- /dev/null
+++ b/lib/NuGet.config
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/lib/PuppeteerSharp.AspNetFramework.sln b/lib/PuppeteerSharp.AspNetFramework.sln
deleted file mode 100644
index a62c7d5a1..000000000
--- a/lib/PuppeteerSharp.AspNetFramework.sln
+++ /dev/null
@@ -1,60 +0,0 @@
-
-Microsoft Visual Studio Solution File, Format Version 12.00
-# Visual Studio 15
-VisualStudioVersion = 15.0.27703.2035
-MinimumVisualStudioVersion = 10.0.40219.1
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "PuppeteerSharp", "PuppeteerSharp\PuppeteerSharp.csproj", "{19B9B1ED-AF6C-4DAF-8B73-401570111F88}"
-EndProject
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "PuppeteerSharp.Tests", "PuppeteerSharp.Tests\PuppeteerSharp.Tests.csproj", "{1682289E-5ED3-405F-8ABC-01A3ED58CBC6}"
-EndProject
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "PuppeteerSharp.TestServer", "PuppeteerSharp.TestServer\PuppeteerSharp.TestServer.csproj", "{0CC393AB-10C2-4CDB-8353-78924D3DD5D3}"
-EndProject
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "PuppeteerSharp.Tests.DumpIO", "PuppeteerSharp.Tests.DumpIO\PuppeteerSharp.Tests.DumpIO.csproj", "{B1892212-CEE3-4DC3-ADB8-04A2D9A081A0}"
-EndProject
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "PuppeteerSharp.DevicesFetcher", "PuppeteerSharp.DevicesFetcher\PuppeteerSharp.DevicesFetcher.csproj", "{A500694A-3649-4474-BC71-C835FA19B865}"
-EndProject
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "PuppeteerSharp.AspNetFramework", "PuppeteerSharp.AspNetFramework\PuppeteerSharp.AspNetFramework.csproj", "{4B1A22F5-5AFC-4A29-975E-42D9B377D933}"
-EndProject
-Global
- GlobalSection(SolutionConfigurationPlatforms) = preSolution
- Debug|Any CPU = Debug|Any CPU
- Release|Any CPU = Release|Any CPU
- EndGlobalSection
- GlobalSection(ProjectConfigurationPlatforms) = postSolution
- {19B9B1ED-AF6C-4DAF-8B73-401570111F88}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {19B9B1ED-AF6C-4DAF-8B73-401570111F88}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {19B9B1ED-AF6C-4DAF-8B73-401570111F88}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {19B9B1ED-AF6C-4DAF-8B73-401570111F88}.Release|Any CPU.Build.0 = Release|Any CPU
- {1682289E-5ED3-405F-8ABC-01A3ED58CBC6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {1682289E-5ED3-405F-8ABC-01A3ED58CBC6}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {1682289E-5ED3-405F-8ABC-01A3ED58CBC6}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {1682289E-5ED3-405F-8ABC-01A3ED58CBC6}.Release|Any CPU.Build.0 = Release|Any CPU
- {0CC393AB-10C2-4CDB-8353-78924D3DD5D3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {0CC393AB-10C2-4CDB-8353-78924D3DD5D3}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {0CC393AB-10C2-4CDB-8353-78924D3DD5D3}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {0CC393AB-10C2-4CDB-8353-78924D3DD5D3}.Release|Any CPU.Build.0 = Release|Any CPU
- {B1892212-CEE3-4DC3-ADB8-04A2D9A081A0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {B1892212-CEE3-4DC3-ADB8-04A2D9A081A0}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {B1892212-CEE3-4DC3-ADB8-04A2D9A081A0}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {B1892212-CEE3-4DC3-ADB8-04A2D9A081A0}.Release|Any CPU.Build.0 = Release|Any CPU
- {A500694A-3649-4474-BC71-C835FA19B865}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {A500694A-3649-4474-BC71-C835FA19B865}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {A500694A-3649-4474-BC71-C835FA19B865}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {A500694A-3649-4474-BC71-C835FA19B865}.Release|Any CPU.Build.0 = Release|Any CPU
- {4B1A22F5-5AFC-4A29-975E-42D9B377D933}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {4B1A22F5-5AFC-4A29-975E-42D9B377D933}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {4B1A22F5-5AFC-4A29-975E-42D9B377D933}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {4B1A22F5-5AFC-4A29-975E-42D9B377D933}.Release|Any CPU.Build.0 = Release|Any CPU
- EndGlobalSection
- GlobalSection(SolutionProperties) = preSolution
- HideSolutionNode = FALSE
- EndGlobalSection
- GlobalSection(ExtensibilityGlobals) = postSolution
- SolutionGuid = {F9F7978B-89C0-4A54-8D80-A1E93E401D4C}
- EndGlobalSection
- GlobalSection(MonoDevelopProperties) = preSolution
- Policies = $0
- $0.DotNetNamingPolicy = $1
- $1.DirectoryNamespaceAssociation = PrefixedHierarchical
- EndGlobalSection
-EndGlobal
diff --git a/lib/PuppeteerSharp.AspNetFramework/AspNetWebSocketTransport.cs b/lib/PuppeteerSharp.AspNetFramework/AspNetWebSocketTransport.cs
deleted file mode 100644
index 410d1d8f8..000000000
--- a/lib/PuppeteerSharp.AspNetFramework/AspNetWebSocketTransport.cs
+++ /dev/null
@@ -1,54 +0,0 @@
-using System;
-using System.Net.WebSockets;
-using System.Threading;
-using System.Threading.Tasks;
-using System.Web.Hosting;
-using PuppeteerSharp.Transport;
-
-namespace PuppeteerSharp.AspNetFramework
-{
- public class AspNetWebSocketTransport : WebSocketTransport
- {
- #region Static fields
-
- ///
- /// Gets a that creates instances.
- ///
- public static readonly TransportFactory AspNetTransportFactory = CreateAspNetTransport;
-
- ///
- /// Gets a that uses ASP.NET
- /// for scheduling of tasks.
- ///
- public static readonly TransportTaskScheduler AspNetTransportScheduler = ScheduleBackgroundTask;
-
- #endregion
-
- #region Static methods
-
- private static async Task CreateAspNetTransport(Uri url, IConnectionOptions connectionOptions, CancellationToken cancellationToken)
- {
- var webSocketFactory = connectionOptions.WebSocketFactory ?? DefaultWebSocketFactory;
- var webSocket = await webSocketFactory(url, connectionOptions, cancellationToken);
- return new AspNetWebSocketTransport(webSocket, connectionOptions.EnqueueTransportMessages);
- }
-
- private static void ScheduleBackgroundTask(Func taskFactory, CancellationToken cancellationToken)
- {
- Task ExecuteAsync(CancellationToken hostingCancellationToken)
- => taskFactory(CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, hostingCancellationToken).Token);
- HostingEnvironment.QueueBackgroundWorkItem(ExecuteAsync);
- }
-
- #endregion
-
- #region Constructor(s)
-
- ///
- public AspNetWebSocketTransport(WebSocket client, bool queueRequests)
- : base(client, AspNetTransportScheduler, queueRequests)
- { }
-
- #endregion
- }
-}
diff --git a/lib/PuppeteerSharp.AspNetFramework/PuppeteerSharp.AspNetFramework.csproj b/lib/PuppeteerSharp.AspNetFramework/PuppeteerSharp.AspNetFramework.csproj
deleted file mode 100644
index 7e6731088..000000000
--- a/lib/PuppeteerSharp.AspNetFramework/PuppeteerSharp.AspNetFramework.csproj
+++ /dev/null
@@ -1,22 +0,0 @@
-
-
-
- net461
- true
- 1.12.0
- Darío Kondratiuk
- Darío Kondratiuk
- https://github.com/kblok/puppeteer-sharp
- Puppeteer-Sharp Helpers for ASP.NET Full Framework
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/demos/PuppeteerSharpPdfDemo/PuppeteerSharpPdfDemo.csproj b/lib/PuppeteerSharp.DevicesFetcher/CefSharp.Dom.DevicesFetcher.csproj
similarity index 54%
rename from demos/PuppeteerSharpPdfDemo/PuppeteerSharpPdfDemo.csproj
rename to lib/PuppeteerSharp.DevicesFetcher/CefSharp.Dom.DevicesFetcher.csproj
index 7929a45c0..3c3102fc1 100644
--- a/demos/PuppeteerSharpPdfDemo/PuppeteerSharpPdfDemo.csproj
+++ b/lib/PuppeteerSharp.DevicesFetcher/CefSharp.Dom.DevicesFetcher.csproj
@@ -2,9 +2,11 @@
Exe
- netcoreapp3.1
+ net6.0
+
-
+
+
diff --git a/lib/PuppeteerSharp.DevicesFetcher/Program.cs b/lib/PuppeteerSharp.DevicesFetcher/Program.cs
index b2beb8471..a1bb1692a 100644
--- a/lib/PuppeteerSharp.DevicesFetcher/Program.cs
+++ b/lib/PuppeteerSharp.DevicesFetcher/Program.cs
@@ -6,6 +6,7 @@
using System.Text;
using System.Threading.Tasks;
using Newtonsoft.Json;
+
namespace PuppeteerSharp.DevicesFetcher
{
class Program
@@ -54,7 +55,7 @@ static void WriteDeviceDescriptors(IEnumerable devices)
using System.Collections.Generic;
using System.Collections.ObjectModel;
-namespace PuppeteerSharp.Mobile
+namespace CefSharp.Dom.Mobile
{
///
/// Device descriptors.
@@ -67,18 +68,10 @@ public static class DeviceDescriptors
var end = @"
};
- private static Lazy> _readOnlyDevices =
+ private static readonly Lazy> _readOnlyDevices =
new Lazy>(() => new ReadOnlyDictionary(Devices));
internal static IReadOnlyDictionary ToReadOnly() => _readOnlyDevices.Value;
-
- ///
- /// Get the specified device description.
- ///
- /// The device descriptor.
- /// Device Name.
- [Obsolete(""Use Puppeteer.Devices instead"")]
- public static DeviceDescriptor Get(DeviceDescriptorName name) => Devices[name];
}
}";
@@ -92,7 +85,7 @@ public static class DeviceDescriptors
static void WriteDeviceDescriptorName(IEnumerable devices)
{
var builder = new StringBuilder();
- var begin = @"namespace PuppeteerSharp.Mobile
+ var begin = @"namespace CefSharp.Dom.Mobile
{
///
/// Device descriptor name.
diff --git a/lib/PuppeteerSharp.DevicesFetcher/PuppeteerSharp.DevicesFetcher.csproj b/lib/PuppeteerSharp.DevicesFetcher/PuppeteerSharp.DevicesFetcher.csproj
deleted file mode 100644
index d3e08dd45..000000000
--- a/lib/PuppeteerSharp.DevicesFetcher/PuppeteerSharp.DevicesFetcher.csproj
+++ /dev/null
@@ -1,15 +0,0 @@
-
-
-
- Exe
- net5.0
-
-
-
-
-
-
-
-
-
-
diff --git a/lib/PuppeteerSharp.TestServer/PuppeteerSharp.TestServer.csproj b/lib/PuppeteerSharp.TestServer/CefSharp.Dom.TestServer.csproj
similarity index 100%
rename from lib/PuppeteerSharp.TestServer/PuppeteerSharp.TestServer.csproj
rename to lib/PuppeteerSharp.TestServer/CefSharp.Dom.TestServer.csproj
diff --git a/lib/PuppeteerSharp.TestServer/SimpleCompressionMiddleware.cs b/lib/PuppeteerSharp.TestServer/SimpleCompressionMiddleware.cs
index 06660f436..7b00ac992 100644
--- a/lib/PuppeteerSharp.TestServer/SimpleCompressionMiddleware.cs
+++ b/lib/PuppeteerSharp.TestServer/SimpleCompressionMiddleware.cs
@@ -1,4 +1,3 @@
-using System;
using System.IO;
using System.IO.Compression;
using System.Threading.Tasks;
@@ -45,4 +44,4 @@ public async Task Invoke(HttpContext context)
}
}
}
-}
\ No newline at end of file
+}
diff --git a/lib/PuppeteerSharp.TestServer/wwwroot/dataattributes.html b/lib/PuppeteerSharp.TestServer/wwwroot/dataattributes.html
new file mode 100644
index 000000000..826e7b9f8
--- /dev/null
+++ b/lib/PuppeteerSharp.TestServer/wwwroot/dataattributes.html
@@ -0,0 +1,11 @@
+
+
+
+
+ DevTools DOM Data Attribute Testing
+
+
+ Testing
+ Test Page
+
+
diff --git a/lib/PuppeteerSharp.TestServer/wwwroot/index.html b/lib/PuppeteerSharp.TestServer/wwwroot/index.html
new file mode 100644
index 000000000..1e1696ceb
--- /dev/null
+++ b/lib/PuppeteerSharp.TestServer/wwwroot/index.html
@@ -0,0 +1,14 @@
+
+
+
+
+ DevTools DOM Testing
+
+
+
+ Testing
+ Test Page
+
+
diff --git a/lib/PuppeteerSharp.TestServer/wwwroot/input/button.html b/lib/PuppeteerSharp.TestServer/wwwroot/input/button.html
index d4c6e13fd..81cb2b2c5 100644
--- a/lib/PuppeteerSharp.TestServer/wwwroot/input/button.html
+++ b/lib/PuppeteerSharp.TestServer/wwwroot/input/button.html
@@ -6,6 +6,7 @@
Click target
+ GitHub.com
-