Skip to content

Commit

Permalink
Merge 848e1eb into 26995e7
Browse files Browse the repository at this point in the history
  • Loading branch information
amaitland authored Dec 7, 2024
2 parents 26995e7 + 848e1eb commit 440a946
Show file tree
Hide file tree
Showing 35 changed files with 3,204 additions and 145 deletions.
113 changes: 113 additions & 0 deletions CefSharp.Test/Wpf.HwndHost/WpfBrowserTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
// Copyright © 2017 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.Runtime.InteropServices;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Interop;
using CefSharp.Example;
using CefSharp.Wpf.HwndHost;
using Xunit;
using Xunit.Abstractions;

namespace CefSharp.Test.Wpf.HwndHost
{
//NOTE: All Test classes must be part of this collection as it manages the Cef Initialize/Shutdown lifecycle
[Collection(CefSharpFixtureCollection.Key)]
[BrowserRefCountDebugging(typeof(ChromiumWebBrowser))]
public class WpfBrowserTests
{
[DllImport("user32.dll")]
private static extern IntPtr SetParent(IntPtr hwnd, IntPtr hwndNewParent);

private const int HWND_MESSAGE = -3;

private readonly ITestOutputHelper output;
private readonly CefSharpFixture fixture;

public WpfBrowserTests(ITestOutputHelper output, CefSharpFixture fixture)
{
this.fixture = fixture;
this.output = output;
}

[WpfFact]
public async Task ShouldWorkWhenLoadingGoogle()
{
var window = CreateAndShowHiddenWindow();

using (var browser = new ChromiumWebBrowser("www.google.com"))
{
window.Content = browser;

await browser.WaitForInitialLoadAsync();
var mainFrame = browser.GetMainFrame();

Assert.True(mainFrame.IsValid);
Assert.Contains("www.google", mainFrame.Url);

output.WriteLine("Url {0}", mainFrame.Url);
}
}

[WpfFact]
public async Task ShouldWorkWhenLoadUrlAsyncImmediately()
{
var window = CreateAndShowHiddenWindow();

using (var browser = new ChromiumWebBrowser(string.Empty))
{
window.Content = browser;

var response = await browser.LoadUrlAsync("www.google.com");
var mainFrame = browser.GetMainFrame();

Assert.True(response.Success);
Assert.True(mainFrame.IsValid);
Assert.Contains("www.google", mainFrame.Url);

output.WriteLine("Url {0}", mainFrame.Url);
}
}

[WpfFact]
public async Task ShouldRespectDisposed()
{
var window = CreateAndShowHiddenWindow();

ChromiumWebBrowser browser;

using (browser = new ChromiumWebBrowser(CefExample.DefaultUrl))
{
window.Content = browser;

await browser.WaitForInitialLoadAsync();
}

Assert.True(browser.IsDisposed);

var ex = Assert.Throws<ObjectDisposedException>(() =>
{
browser.Copy();
});
}

private static Window CreateAndShowHiddenWindow()
{
var window = new Window();
window.Width = 1024;
window.Height = 768;

var helper = new WindowInteropHelper(window);

helper.EnsureHandle();

SetParent(helper.Handle, (IntPtr)HWND_MESSAGE);

window.Show();
return window;
}
}
}
6 changes: 6 additions & 0 deletions CefSharp.Wpf.HwndHost.Example/App.config
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6.2" />
</startup>
</configuration>
11 changes: 11 additions & 0 deletions CefSharp.Wpf.HwndHost.Example/App.xaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<Application x:Class="CefSharp.Wpf.HwndHost.Example.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:converter="clr-namespace:CefSharp.Wpf.HwndHost.Example.Converter"
StartupUri="MainWindow.xaml">
<Application.Resources>
<converter:TitleConverter x:Key="TitleConverter"/>
<converter:EnvironmentConverter x:Key="EnvironmentConverter" />
<BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter" />
</Application.Resources>
</Application>
62 changes: 62 additions & 0 deletions CefSharp.Wpf.HwndHost.Example/App.xaml.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
// Copyright © 2019 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.IO;
using System.Windows;
using CefSharp.Wpf.HwndHost.Handler;

namespace CefSharp.Wpf.HwndHost.Example
{
/// <summary>
/// Interaction logic for App.xaml
/// </summary>
public partial class App : Application
{
public App()
{
#if !NETCOREAPP3_1_OR_GREATER
CefRuntime.SubscribeAnyCpuAssemblyResolver();
#endif
}

protected override void OnStartup(StartupEventArgs e)
{
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");

//See https://github.com/cefsharp/CefSharp/wiki/General-Usage#multithreadedmessageloop
//The default is true
const bool multiThreadedMessageLoop = true;

IBrowserProcessHandler browserProcessHandler = null;

if(!multiThreadedMessageLoop)
{
settings.MultiThreadedMessageLoop = false;
browserProcessHandler = new IntegratedMessageLoopBrowserProcessHandler(Dispatcher);
}

// Make sure you set performDependencyCheck false
Cef.Initialize(settings, performDependencyCheck: false, browserProcessHandler: browserProcessHandler);

base.OnStartup(e);
}
}
}
14 changes: 14 additions & 0 deletions CefSharp.Wpf.HwndHost.Example/AssemblyInfo.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
// Copyright © 2019 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.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)
)]
34 changes: 34 additions & 0 deletions CefSharp.Wpf.HwndHost.Example/Behaviours/HoverLinkBehaviour.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
using System.Windows;
using System;
using Microsoft.Xaml.Behaviors;

namespace CefSharp.Wpf.HwndHost.Example.Behaviours
{
public class HoverLinkBehaviour : Behavior<ChromiumWebBrowser>
{
// Using a DependencyProperty as the backing store for HoverLink. This enables animation, styling, binding, etc...
public static readonly DependencyProperty HoverLinkProperty = DependencyProperty.Register("HoverLink", typeof(string), typeof(HoverLinkBehaviour), new PropertyMetadata(string.Empty));

public string HoverLink
{
get { return (string)GetValue(HoverLinkProperty); }
set { SetValue(HoverLinkProperty, value); }
}

protected override void OnAttached()
{
AssociatedObject.StatusMessage += OnStatusMessageChanged;
}

protected override void OnDetaching()
{
AssociatedObject.StatusMessage -= OnStatusMessageChanged;
}

private void OnStatusMessageChanged(object sender, StatusMessageEventArgs e)
{
var chromiumWebBrowser = sender as ChromiumWebBrowser;
chromiumWebBrowser.Dispatcher.BeginInvoke((Action)(() => HoverLink = e.Value));
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
using System.Windows.Controls;
using System.Windows.Input;
using Microsoft.Xaml.Behaviors;

namespace CefSharp.Wpf.HwndHost.Example.Behaviours
{
public class TextBoxBindingUpdateOnEnterBehaviour : Behavior<TextBox>
{
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();
}
}
}
}
50 changes: 50 additions & 0 deletions CefSharp.Wpf.HwndHost.Example/CefSharp.Wpf.HwndHost.Example.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>net472</TargetFrameworks>
<OutputType>WinExe</OutputType>
<Platforms>x86;x64</Platforms>
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
<UseWPF>true</UseWPF>
<CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
<ApplicationManifest>app.manifest</ApplicationManifest>
<StartupObject>CefSharp.Wpf.HwndHost.Example.App</StartupObject>
<AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
<RuntimeIdentifiers>win7-x86;win7-x64</RuntimeIdentifiers>
<LangVersion>9.0</LangVersion>
</PropertyGroup>

<ItemGroup>
<AppDesigner Include="Properties\" />
</ItemGroup>
<ItemGroup>
<None Update="crash_reporter.cfg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\CefSharp.Core.Runtime\CefSharp.Core.Runtime.vcxproj" />
<ProjectReference Include="..\CefSharp.Core\CefSharp.Core.csproj" />
<ProjectReference Include="..\CefSharp.Wpf\CefSharp.Wpf.csproj" />
<ProjectReference Include="..\CefSharp\CefSharp.csproj" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="chromiumembeddedframework.runtime" Version="131.3.1" />
<PackageReference Include="MaterialDesignThemes" Version="4.8.0" />
<PackageReference Include="Microsoft.Xaml.Behaviors.Wpf" Version="1.1.39" />
<PackageReference Include="Microsoft.CodeAnalysis.NetAnalyzers" Version="8.0.0">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
</ItemGroup>
<ItemGroup>
<Compile Remove="bin.netcore\**" />
<Compile Remove="obj.netcore\**" />
<EmbeddedResource Remove="bin.netcore\**" />
<EmbeddedResource Remove="obj.netcore\**" />
<None Remove="bin.netcore\**" />
<None Remove="obj.netcore\**" />
<Page Remove="bin.netcore\**" />
<Page Remove="obj.netcore\**" />
</ItemGroup>
<Import Project="$(MSBuildThisFileDirectory)..\CefSharp.Native.props" />
</Project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
<?xml version="1.0" encoding="utf-8"?>
<Project>
<!-- Note: We cannot use the recommended style of specifying <Project Sdk=...> because we need
to set BaseIntermediateOutputPath and BaseOutputPath before the SDK props are imported. -->
<PropertyGroup>
<BaseIntermediateOutputPath>obj.netcore\</BaseIntermediateOutputPath>
<BaseOutputPath>bin.netcore\</BaseOutputPath>
</PropertyGroup>

<Import Project="Sdk.props" Sdk="Microsoft.NET.Sdk.WindowsDesktop" />

<PropertyGroup>
<OutputType>WinExe</OutputType>
<TargetFrameworks>netcoreapp3.1;net5.0-windows</TargetFrameworks>
<TargetFrameworks Condition="'$(VisualStudioVersion)'=='17.0'">$(TargetFrameworks);net6.0-windows</TargetFrameworks>
<RootNamespace>CefSharp.Wpf.HwndHost.Example</RootNamespace>
<AssemblyName>CefSharp.Wpf.HwndHost.Example</AssemblyName>
<UseWPF>true</UseWPF>
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
<ApplicationManifest>app.manifest</ApplicationManifest>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
<!-- Builds failing for arm64 on appveyor for some reason-->
<!--<Platforms>x86;x64;arm64</Platforms>-->
<Platforms>x86;x64</Platforms>
<!-- Explicitly set the PlatformTarget for arm64, see: https://github.com/dotnet/sdk/issues/15434 -->
<PlatformTarget Condition="'$(Platform)' == 'arm64'">arm64</PlatformTarget>
<StartupObject>CefSharp.Wpf.HwndHost.Example.App</StartupObject>
<!--
Run on a newer version of .Net if the specified version (.Net Core 3.1) is not installed
https://github.com/dotnet/docs/issues/12237
-->
<RollForward>Major</RollForward>
<RuntimeIdentifiers>win-x86;win-x64</RuntimeIdentifiers>
<RuntimeIdentifier Condition="'$(Platform)' == 'x86'">win-x86</RuntimeIdentifier>
<RuntimeIdentifier Condition="'$(Platform)' == 'x64'">win-x64</RuntimeIdentifier>
<RuntimeIdentifier Condition="'$(Platform)' == 'arm64'">win-arm64</RuntimeIdentifier>
<SelfContained Condition="'$(SelfContained)' == ''">false</SelfContained>
<LangVersion>9.0</LangVersion>
</PropertyGroup>

<ItemGroup>
<ProjectReference Include="..\CefSharp.Core\CefSharp.Core.netcore.csproj" />
<ProjectReference Include="..\CefSharp.Wpf\CefSharp.Wpf.netcore.csproj" />
<ProjectReference Include="..\CefSharp\CefSharp.netcore.csproj" />
<PackageReference Include="chromiumembeddedframework.runtime" Version="131.3.1" />
<PackageReference Include="Microsoft.CodeAnalysis.NetAnalyzers" Version="8.0.0">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="System.Runtime.InteropServices.WindowsRuntime" Version="4.3.0" />
<PackageReference Include="MaterialDesignThemes" Version="4.8.0" />
</ItemGroup>

<ItemGroup>
<None Include="crash_reporter.cfg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
</ItemGroup>

<ItemGroup>
<!-- Don't include items from the "bin" and "obj" folders used by the .NET Framework projects. -->
<None Remove="bin/**/*.*" />
<None Remove="obj/**/*.*" />
<Compile Remove="obj/**/*.*" />
</ItemGroup>

<Import Project="$(MSBuildThisFileDirectory)..\CefSharp.AfterBuild.targets" />
<Import Project="Sdk.targets" Sdk="Microsoft.NET.Sdk.WindowsDesktop" />
</Project>
Loading

0 comments on commit 440a946

Please sign in to comment.