Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// GenAPI Version: 5.0.2.37403
Expand Down Expand Up @@ -291,6 +291,7 @@ protected virtual void Dispose(bool A_0) { }
public virtual System.Threading.Tasks.Task<CefSharp.ResolveCallbackResult> ResolveHostAsync(System.Uri origin) { throw null; }
public virtual void SetContentSetting(string requestingUrl, string topLevelUrl, CefSharp.Enums.ContentSettingTypes contentType, CefSharp.Enums.ContentSettingValues value) { }
public virtual bool SetPreference(string name, object value, out string error) { throw null; }
public virtual CefSharp.IRegistration AddPreferenceObserver(string name, CefSharp.Callback.IPreferenceObserver observer) { throw null; }
public virtual void SetWebsiteSetting(string requestingUrl, string topLevelUrl, CefSharp.Enums.ContentSettingTypes contentType, object value) { }
public virtual CefSharp.IRequestContext UnWrap() { throw null; }
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -418,6 +418,7 @@
<ClInclude Include="Internals\CefRequestContextHandlerAdapter.h" />
<ClInclude Include="PostData.h" />
<ClInclude Include="PostDataElement.h" />
<ClInclude Include="Internals\PreferenceObserverAdapter.h" />
<ClInclude Include="Request.h" />
<ClInclude Include="resource.h" />
<ClInclude Include="UrlRequest.h" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -325,6 +325,9 @@
<ClInclude Include="Internals\CefTaskDelegate.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Internals\PreferenceObserverAdapter.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClInclude Include="Internals\CefFrameWrapper.h">
Expand Down
1 change: 1 addition & 0 deletions CefSharp.Core.Runtime/CefSharp.Core.Runtime.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -317,6 +317,7 @@
<ClInclude Include="Internals\CefRequestContextHandlerAdapter.h" />
<ClInclude Include="PostData.h" />
<ClInclude Include="PostDataElement.h" />
<ClInclude Include="Internals\PreferenceObserverAdapter.h" />
<ClInclude Include="Request.h" />
<ClInclude Include="resource.h" />
<ClInclude Include="UrlRequest.h" />
Expand Down
3 changes: 3 additions & 0 deletions CefSharp.Core.Runtime/CefSharp.Core.Runtime.vcxproj.filters
Original file line number Diff line number Diff line change
Expand Up @@ -319,6 +319,9 @@
<ClInclude Include="Internals\CefTaskDelegate.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Internals\PreferenceObserverAdapter.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Internals\CefPermissionPromptCallbackWrapper.h">
<Filter>Header Files</Filter>
</ClInclude>
Expand Down
41 changes: 41 additions & 0 deletions CefSharp.Core.Runtime/Internals/PreferenceObserverAdapter.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
// Copyright © 2026 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.

#include "include/cef_preference.h"
#include <gcroot.h>

#include "StringUtils.h"

using namespace CefSharp::Callback;

namespace CefSharp
{
namespace Internals
{
private class PreferenceObserverAdapter : public CefPreferenceObserver
{
private:
gcroot<IPreferenceObserver^> _handler;

public:
PreferenceObserverAdapter(IPreferenceObserver^ handler)
{
_handler = handler;
}

~PreferenceObserverAdapter()
{
delete _handler;
_handler = nullptr;
}

virtual void OnPreferenceChanged(const CefString& name) override
{
_handler->OnPreferenceChanged(StringUtils::ToClr(name));
}

IMPLEMENT_REFCOUNTINGM(PreferenceObserverAdapter);
};
}
}
14 changes: 14 additions & 0 deletions CefSharp.Core.Runtime/RequestContext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,12 @@
#include "Internals\CefSchemeHandlerFactoryAdapter.h"
#include "Internals\CefCompletionCallbackAdapter.h"
#include "Internals\CefResolveCallbackAdapter.h"
#include "Internals\PreferenceObserverAdapter.h"
#include "Internals\TypeConversion.h"
#include "Internals\CefRegistrationWrapper.h"

using namespace System::Runtime::InteropServices;
using namespace CefSharp::Callback;

namespace CefSharp
{
Expand Down Expand Up @@ -117,6 +120,17 @@ namespace CefSharp
return success;
}

IRegistration^ RequestContext::AddPreferenceObserver(String^ name, IPreferenceObserver^ observer)
{
ThrowIfDisposed();

ThrowIfExecutedOnNonCefUiThread();

auto registration = _requestContext->AddPreferenceObserver(StringUtils::ToNative(name), new PreferenceObserverAdapter(observer));

return gcnew CefRegistrationWrapper(registration);
}

void RequestContext::ClearCertificateExceptions(ICompletionCallback^ callback)
{
ThrowIfDisposed();
Expand Down
18 changes: 18 additions & 0 deletions CefSharp.Core.Runtime/RequestContext.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

using namespace System::Runtime::InteropServices;
using namespace System::Threading::Tasks;
using namespace CefSharp::Callback;

namespace CefSharp
{
Expand Down Expand Up @@ -254,6 +255,23 @@ namespace CefSharp
/// application thread will be the CEF UI thread.</remarks>
virtual bool CanSetPreference(String^ name);

/// <summary>
/// Add an observer for preference changes. <paramref name="name"/> is the name of the
/// preference to observe. If <paramref name="name"/> is empty then all preferences will
/// be observed. Observing all preferences has performance consequences and
/// is not recommended outside of testing scenarios. The observer will remain
/// registered until the returned Registration object is destroyed. This
/// method must be called on the browser process UI thread.
/// </summary>
/// <param name="name">preference key</param>
/// <param name="observer">preference observer</param>
/// <remarks>Use Cef.UIThreadTaskFactory to execute this method if required,
/// <see cref="IBrowserProcessHandler.OnContextInitialized"/> and ChromiumWebBrowser.IsBrowserInitializedChanged are both
/// executed on the CEF UI thread, so can be called directly.
/// When CefSettings.MultiThreadedMessageLoop == false (the default is true) then the main
/// application thread will be the CEF UI thread.</remarks>
virtual IRegistration^ AddPreferenceObserver(String^ name, IPreferenceObserver^ observer);

/// <summary>
/// Set the value associated with preference name. If value is null the
/// preference will be restored to its default value. If setting the preference
Expand Down
7 changes: 7 additions & 0 deletions CefSharp.Core/RequestContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using CefSharp.Callback;
using CefSharp.Enums;

namespace CefSharp
Expand Down Expand Up @@ -174,6 +175,12 @@ public bool SetPreference(string name, object value, out string error)
return requestContext.SetPreference(name, value, out error);
}

/// <inheritdoc/>
public IRegistration AddPreferenceObserver(string name, IPreferenceObserver observer)
{
return requestContext.AddPreferenceObserver(name, observer);
}

/// <inheritdoc/>
public void ClearCertificateExceptions(ICompletionCallback callback)
{
Expand Down
23 changes: 23 additions & 0 deletions CefSharp/Callback/IPreferenceObserver.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
// Copyright © 2026 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;

namespace CefSharp.Callback
{
/// <summary>
/// Implemented by the client to observe preference changes and registered via
/// <see cref="IRequestContext.AddPreferenceObserver"/>. The methods of this class will
/// be called on the browser process UI thread.
/// </summary>
public interface IPreferenceObserver : IDisposable
{
/// <summary>
/// Called when a preference has changed. The new value can be retrieved using
/// <see cref="IRequestContext.GetPreference"/>.
/// </summary>
/// <param name="name">preference key</param>
void OnPreferenceChanged(string name);
}
}
18 changes: 18 additions & 0 deletions CefSharp/IRequestContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using CefSharp.Callback;
using CefSharp.Enums;

namespace CefSharp
Expand Down Expand Up @@ -158,6 +159,23 @@ public interface IRequestContext : IDisposable
/// application thread will be the CEF UI thread.</remarks>
bool SetPreference(string name, object value, out string error);

/// <summary>
/// Add an observer for preference changes. <paramref name="name"/> is the name of the
/// preference to observe. If <paramref name="name"/> is empty then all preferences will
/// be observed. Observing all preferences has performance consequences and
/// is not recommended outside of testing scenarios. The observer will remain
/// registered until the returned Registration object is destroyed. This
/// method must be called on the browser process UI thread.
/// </summary>
/// <param name="name">preference key</param>
/// <param name="observer">preference observer</param>
/// <remarks>Use Cef.UIThreadTaskFactory to execute this method if required,
/// <see cref="IBrowserProcessHandler.OnContextInitialized"/> and ChromiumWebBrowser.IsBrowserInitializedChanged are both
/// executed on the CEF UI thread, so can be called directly.
/// When CefSettings.MultiThreadedMessageLoop == false (the default is true) then the main
/// application thread will be the CEF UI thread.</remarks>
IRegistration AddPreferenceObserver(string name, IPreferenceObserver observer);

/// <summary>
/// Clears all certificate exceptions that were added as part of handling
/// <see cref="IRequestHandler.OnCertificateError"/>. If you call this it is
Expand Down