Skip to content

Commit f43cd64

Browse files
authored
Import CefSharp.Wpf.HwndHost into main repository. (#4981)
* HwndHost - Initial import * HwndHost - Add Example to solution and use common IWpfChromiumWebBrowser interface * HwndHost - Update UpdateNugetPackages.ps1 * HwndHost - Add Nuspec * HwndHost Example - Upgrade version * HwndHost Example - Try non self contained build for debug and release * Test - Add basic HwndHost tests Probably need to revisit these, little bit hacky creating the window * HwndHost - Allow any RequestContext that inherits from Core.RequestContext Cheery pick of cefsharp/CefSharp.Wpf.HwndHost#31 * HwndHost Example - Disable arm64 Example will be removed shortly, so it doesn't matter too much now. It will be moved to MinimalExample and the Wpf Example expanded * HwndHost - Delete delegate command * Upgrade packages * Nuget - Move Nuspec file to PackageReference folder --------- Co-authored-by: amaitland <307872+amaitland@users.noreply.github.com>
1 parent aed9ffd commit f43cd64

35 files changed

Lines changed: 3204 additions & 145 deletions
Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
// Copyright © 2017 The CefSharp Authors. All rights reserved.
2+
//
3+
// Use of this source code is governed by a BSD-style license that can be found in the LICENSE file.
4+
5+
using System;
6+
using System.Runtime.InteropServices;
7+
using System.Threading.Tasks;
8+
using System.Windows;
9+
using System.Windows.Interop;
10+
using CefSharp.Example;
11+
using CefSharp.Wpf.HwndHost;
12+
using Xunit;
13+
using Xunit.Abstractions;
14+
15+
namespace CefSharp.Test.Wpf.HwndHost
16+
{
17+
//NOTE: All Test classes must be part of this collection as it manages the Cef Initialize/Shutdown lifecycle
18+
[Collection(CefSharpFixtureCollection.Key)]
19+
[BrowserRefCountDebugging(typeof(ChromiumWebBrowser))]
20+
public class WpfBrowserTests
21+
{
22+
[DllImport("user32.dll")]
23+
private static extern IntPtr SetParent(IntPtr hwnd, IntPtr hwndNewParent);
24+
25+
private const int HWND_MESSAGE = -3;
26+
27+
private readonly ITestOutputHelper output;
28+
private readonly CefSharpFixture fixture;
29+
30+
public WpfBrowserTests(ITestOutputHelper output, CefSharpFixture fixture)
31+
{
32+
this.fixture = fixture;
33+
this.output = output;
34+
}
35+
36+
[WpfFact]
37+
public async Task ShouldWorkWhenLoadingGoogle()
38+
{
39+
var window = CreateAndShowHiddenWindow();
40+
41+
using (var browser = new ChromiumWebBrowser("www.google.com"))
42+
{
43+
window.Content = browser;
44+
45+
await browser.WaitForInitialLoadAsync();
46+
var mainFrame = browser.GetMainFrame();
47+
48+
Assert.True(mainFrame.IsValid);
49+
Assert.Contains("www.google", mainFrame.Url);
50+
51+
output.WriteLine("Url {0}", mainFrame.Url);
52+
}
53+
}
54+
55+
[WpfFact]
56+
public async Task ShouldWorkWhenLoadUrlAsyncImmediately()
57+
{
58+
var window = CreateAndShowHiddenWindow();
59+
60+
using (var browser = new ChromiumWebBrowser(string.Empty))
61+
{
62+
window.Content = browser;
63+
64+
var response = await browser.LoadUrlAsync("www.google.com");
65+
var mainFrame = browser.GetMainFrame();
66+
67+
Assert.True(response.Success);
68+
Assert.True(mainFrame.IsValid);
69+
Assert.Contains("www.google", mainFrame.Url);
70+
71+
output.WriteLine("Url {0}", mainFrame.Url);
72+
}
73+
}
74+
75+
[WpfFact]
76+
public async Task ShouldRespectDisposed()
77+
{
78+
var window = CreateAndShowHiddenWindow();
79+
80+
ChromiumWebBrowser browser;
81+
82+
using (browser = new ChromiumWebBrowser(CefExample.DefaultUrl))
83+
{
84+
window.Content = browser;
85+
86+
await browser.WaitForInitialLoadAsync();
87+
}
88+
89+
Assert.True(browser.IsDisposed);
90+
91+
var ex = Assert.Throws<ObjectDisposedException>(() =>
92+
{
93+
browser.Copy();
94+
});
95+
}
96+
97+
private static Window CreateAndShowHiddenWindow()
98+
{
99+
var window = new Window();
100+
window.Width = 1024;
101+
window.Height = 768;
102+
103+
var helper = new WindowInteropHelper(window);
104+
105+
helper.EnsureHandle();
106+
107+
SetParent(helper.Handle, (IntPtr)HWND_MESSAGE);
108+
109+
window.Show();
110+
return window;
111+
}
112+
}
113+
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
<?xml version="1.0" encoding="utf-8" ?>
2+
<configuration>
3+
<startup>
4+
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6.2" />
5+
</startup>
6+
</configuration>
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
<Application x:Class="CefSharp.Wpf.HwndHost.Example.App"
2+
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
3+
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
4+
xmlns:converter="clr-namespace:CefSharp.Wpf.HwndHost.Example.Converter"
5+
StartupUri="MainWindow.xaml">
6+
<Application.Resources>
7+
<converter:TitleConverter x:Key="TitleConverter"/>
8+
<converter:EnvironmentConverter x:Key="EnvironmentConverter" />
9+
<BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter" />
10+
</Application.Resources>
11+
</Application>
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
// Copyright © 2019 The CefSharp Authors. All rights reserved.
2+
//
3+
// Use of this source code is governed by a BSD-style license that can be found in the LICENSE file.
4+
5+
using System;
6+
using System.IO;
7+
using System.Windows;
8+
using CefSharp.Wpf.HwndHost.Handler;
9+
10+
namespace CefSharp.Wpf.HwndHost.Example
11+
{
12+
/// <summary>
13+
/// Interaction logic for App.xaml
14+
/// </summary>
15+
public partial class App : Application
16+
{
17+
public App()
18+
{
19+
#if !NETCOREAPP3_1_OR_GREATER
20+
CefRuntime.SubscribeAnyCpuAssemblyResolver();
21+
#endif
22+
}
23+
24+
protected override void OnStartup(StartupEventArgs e)
25+
{
26+
var settings = new CefSettings()
27+
{
28+
//By default CefSharp will use an in-memory cache, you need to specify a Cache Folder to persist data
29+
CachePath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "CefSharp\\Cache")
30+
};
31+
32+
//Example of setting a command line argument
33+
//Enables WebRTC
34+
// - 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
35+
// - CEF Doesn't currently support displaying a UI for media access permissions
36+
//
37+
//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
38+
settings.CefCommandLineArgs.Add("enable-media-stream");
39+
//https://peter.sh/experiments/chromium-command-line-switches/#use-fake-ui-for-media-stream
40+
settings.CefCommandLineArgs.Add("use-fake-ui-for-media-stream");
41+
//For screen sharing add (see https://bitbucket.org/chromiumembedded/cef/issues/2582/allow-run-time-handling-of-media-access#comment-58677180)
42+
settings.CefCommandLineArgs.Add("enable-usermedia-screen-capturing");
43+
44+
//See https://github.com/cefsharp/CefSharp/wiki/General-Usage#multithreadedmessageloop
45+
//The default is true
46+
const bool multiThreadedMessageLoop = true;
47+
48+
IBrowserProcessHandler browserProcessHandler = null;
49+
50+
if(!multiThreadedMessageLoop)
51+
{
52+
settings.MultiThreadedMessageLoop = false;
53+
browserProcessHandler = new IntegratedMessageLoopBrowserProcessHandler(Dispatcher);
54+
}
55+
56+
// Make sure you set performDependencyCheck false
57+
Cef.Initialize(settings, performDependencyCheck: false, browserProcessHandler: browserProcessHandler);
58+
59+
base.OnStartup(e);
60+
}
61+
}
62+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
// Copyright © 2019 The CefSharp Authors. All rights reserved.
2+
//
3+
// Use of this source code is governed by a BSD-style license that can be found in the LICENSE file.
4+
5+
using System.Windows;
6+
7+
[assembly: ThemeInfo(
8+
ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located
9+
//(used if a resource is not found in the page,
10+
// or application resource dictionaries)
11+
ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located
12+
//(used if a resource is not found in the page,
13+
// app, or any theme specific resource dictionaries)
14+
)]
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
using System.Windows;
2+
using System;
3+
using Microsoft.Xaml.Behaviors;
4+
5+
namespace CefSharp.Wpf.HwndHost.Example.Behaviours
6+
{
7+
public class HoverLinkBehaviour : Behavior<ChromiumWebBrowser>
8+
{
9+
// Using a DependencyProperty as the backing store for HoverLink. This enables animation, styling, binding, etc...
10+
public static readonly DependencyProperty HoverLinkProperty = DependencyProperty.Register("HoverLink", typeof(string), typeof(HoverLinkBehaviour), new PropertyMetadata(string.Empty));
11+
12+
public string HoverLink
13+
{
14+
get { return (string)GetValue(HoverLinkProperty); }
15+
set { SetValue(HoverLinkProperty, value); }
16+
}
17+
18+
protected override void OnAttached()
19+
{
20+
AssociatedObject.StatusMessage += OnStatusMessageChanged;
21+
}
22+
23+
protected override void OnDetaching()
24+
{
25+
AssociatedObject.StatusMessage -= OnStatusMessageChanged;
26+
}
27+
28+
private void OnStatusMessageChanged(object sender, StatusMessageEventArgs e)
29+
{
30+
var chromiumWebBrowser = sender as ChromiumWebBrowser;
31+
chromiumWebBrowser.Dispatcher.BeginInvoke((Action)(() => HoverLink = e.Value));
32+
}
33+
}
34+
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
using System.Windows.Controls;
2+
using System.Windows.Input;
3+
using Microsoft.Xaml.Behaviors;
4+
5+
namespace CefSharp.Wpf.HwndHost.Example.Behaviours
6+
{
7+
public class TextBoxBindingUpdateOnEnterBehaviour : Behavior<TextBox>
8+
{
9+
protected override void OnAttached()
10+
{
11+
AssociatedObject.KeyDown += OnTextBoxKeyDown;
12+
}
13+
14+
protected override void OnDetaching()
15+
{
16+
AssociatedObject.KeyDown -= OnTextBoxKeyDown;
17+
}
18+
19+
private void OnTextBoxKeyDown(object sender, KeyEventArgs e)
20+
{
21+
if (e.Key == Key.Enter)
22+
{
23+
var txtBox = sender as TextBox;
24+
txtBox.GetBindingExpression(TextBox.TextProperty).UpdateSource();
25+
}
26+
}
27+
}
28+
}
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
<PropertyGroup>
3+
<TargetFrameworks>net472</TargetFrameworks>
4+
<OutputType>WinExe</OutputType>
5+
<Platforms>x86;x64</Platforms>
6+
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
7+
<UseWPF>true</UseWPF>
8+
<CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
9+
<ApplicationManifest>app.manifest</ApplicationManifest>
10+
<StartupObject>CefSharp.Wpf.HwndHost.Example.App</StartupObject>
11+
<AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
12+
<RuntimeIdentifiers>win7-x86;win7-x64</RuntimeIdentifiers>
13+
<LangVersion>9.0</LangVersion>
14+
</PropertyGroup>
15+
16+
<ItemGroup>
17+
<AppDesigner Include="Properties\" />
18+
</ItemGroup>
19+
<ItemGroup>
20+
<None Update="crash_reporter.cfg">
21+
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
22+
</None>
23+
</ItemGroup>
24+
<ItemGroup>
25+
<ProjectReference Include="..\CefSharp.Core.Runtime\CefSharp.Core.Runtime.vcxproj" />
26+
<ProjectReference Include="..\CefSharp.Core\CefSharp.Core.csproj" />
27+
<ProjectReference Include="..\CefSharp.Wpf\CefSharp.Wpf.csproj" />
28+
<ProjectReference Include="..\CefSharp\CefSharp.csproj" />
29+
</ItemGroup>
30+
<ItemGroup>
31+
<PackageReference Include="chromiumembeddedframework.runtime" Version="131.3.1" />
32+
<PackageReference Include="MaterialDesignThemes" Version="4.8.0" />
33+
<PackageReference Include="Microsoft.Xaml.Behaviors.Wpf" Version="1.1.39" />
34+
<PackageReference Include="Microsoft.CodeAnalysis.NetAnalyzers" Version="8.0.0">
35+
<PrivateAssets>all</PrivateAssets>
36+
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
37+
</PackageReference>
38+
</ItemGroup>
39+
<ItemGroup>
40+
<Compile Remove="bin.netcore\**" />
41+
<Compile Remove="obj.netcore\**" />
42+
<EmbeddedResource Remove="bin.netcore\**" />
43+
<EmbeddedResource Remove="obj.netcore\**" />
44+
<None Remove="bin.netcore\**" />
45+
<None Remove="obj.netcore\**" />
46+
<Page Remove="bin.netcore\**" />
47+
<Page Remove="obj.netcore\**" />
48+
</ItemGroup>
49+
<Import Project="$(MSBuildThisFileDirectory)..\CefSharp.Native.props" />
50+
</Project>
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<Project>
3+
<!-- Note: We cannot use the recommended style of specifying <Project Sdk=...> because we need
4+
to set BaseIntermediateOutputPath and BaseOutputPath before the SDK props are imported. -->
5+
<PropertyGroup>
6+
<BaseIntermediateOutputPath>obj.netcore\</BaseIntermediateOutputPath>
7+
<BaseOutputPath>bin.netcore\</BaseOutputPath>
8+
</PropertyGroup>
9+
10+
<Import Project="Sdk.props" Sdk="Microsoft.NET.Sdk.WindowsDesktop" />
11+
12+
<PropertyGroup>
13+
<OutputType>WinExe</OutputType>
14+
<TargetFrameworks>netcoreapp3.1;net5.0-windows</TargetFrameworks>
15+
<TargetFrameworks Condition="'$(VisualStudioVersion)'=='17.0'">$(TargetFrameworks);net6.0-windows</TargetFrameworks>
16+
<RootNamespace>CefSharp.Wpf.HwndHost.Example</RootNamespace>
17+
<AssemblyName>CefSharp.Wpf.HwndHost.Example</AssemblyName>
18+
<UseWPF>true</UseWPF>
19+
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
20+
<ApplicationManifest>app.manifest</ApplicationManifest>
21+
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
22+
<!-- Builds failing for arm64 on appveyor for some reason-->
23+
<!--<Platforms>x86;x64;arm64</Platforms>-->
24+
<Platforms>x86;x64</Platforms>
25+
<!-- Explicitly set the PlatformTarget for arm64, see: https://github.com/dotnet/sdk/issues/15434 -->
26+
<PlatformTarget Condition="'$(Platform)' == 'arm64'">arm64</PlatformTarget>
27+
<StartupObject>CefSharp.Wpf.HwndHost.Example.App</StartupObject>
28+
<!--
29+
Run on a newer version of .Net if the specified version (.Net Core 3.1) is not installed
30+
https://github.com/dotnet/docs/issues/12237
31+
-->
32+
<RollForward>Major</RollForward>
33+
<RuntimeIdentifiers>win-x86;win-x64</RuntimeIdentifiers>
34+
<RuntimeIdentifier Condition="'$(Platform)' == 'x86'">win-x86</RuntimeIdentifier>
35+
<RuntimeIdentifier Condition="'$(Platform)' == 'x64'">win-x64</RuntimeIdentifier>
36+
<RuntimeIdentifier Condition="'$(Platform)' == 'arm64'">win-arm64</RuntimeIdentifier>
37+
<SelfContained Condition="'$(SelfContained)' == ''">false</SelfContained>
38+
<LangVersion>9.0</LangVersion>
39+
</PropertyGroup>
40+
41+
<ItemGroup>
42+
<ProjectReference Include="..\CefSharp.Core\CefSharp.Core.netcore.csproj" />
43+
<ProjectReference Include="..\CefSharp.Wpf\CefSharp.Wpf.netcore.csproj" />
44+
<ProjectReference Include="..\CefSharp\CefSharp.netcore.csproj" />
45+
<PackageReference Include="chromiumembeddedframework.runtime" Version="131.3.1" />
46+
<PackageReference Include="Microsoft.CodeAnalysis.NetAnalyzers" Version="8.0.0">
47+
<PrivateAssets>all</PrivateAssets>
48+
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
49+
</PackageReference>
50+
<PackageReference Include="System.Runtime.InteropServices.WindowsRuntime" Version="4.3.0" />
51+
<PackageReference Include="MaterialDesignThemes" Version="4.8.0" />
52+
</ItemGroup>
53+
54+
<ItemGroup>
55+
<None Include="crash_reporter.cfg">
56+
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
57+
</None>
58+
</ItemGroup>
59+
60+
<ItemGroup>
61+
<!-- Don't include items from the "bin" and "obj" folders used by the .NET Framework projects. -->
62+
<None Remove="bin/**/*.*" />
63+
<None Remove="obj/**/*.*" />
64+
<Compile Remove="obj/**/*.*" />
65+
</ItemGroup>
66+
67+
<Import Project="$(MSBuildThisFileDirectory)..\CefSharp.AfterBuild.targets" />
68+
<Import Project="Sdk.targets" Sdk="Microsoft.NET.Sdk.WindowsDesktop" />
69+
</Project>

0 commit comments

Comments
 (0)