Skip to content

Commit 76ca699

Browse files
authored
Merge 108b074 into f8ac2d9
2 parents f8ac2d9 + 108b074 commit 76ca699

11 files changed

Lines changed: 235 additions & 0 deletions
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
// Copyright © 2026 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+
#include "Stdafx.h"
6+
7+
#include "CefIdMappers.h"
8+
#include <msclr\marshal_cppstd.h>
9+
#include "include\cef_id_mappers.h"
10+
11+
using namespace msclr::interop;
12+
13+
namespace CefSharp
14+
{
15+
namespace Core
16+
{
17+
int CefIdMappers::CefIdForCommandIdName(String^ name)
18+
{
19+
if (String::IsNullOrEmpty(name))
20+
{
21+
return -1;
22+
}
23+
24+
marshal_context context;
25+
const char* nativePtr = context.marshal_as<const char*>(name);
26+
27+
return cef_id_for_command_id_name(nativePtr);
28+
}
29+
};
30+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
// Copyright © 2026 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+
#pragma once
6+
7+
#include "Stdafx.h"
8+
9+
namespace CefSharp
10+
{
11+
namespace Core
12+
{
13+
/// <exclude />
14+
[System::ComponentModel::EditorBrowsableAttribute(System::ComponentModel::EditorBrowsableState::Never)]
15+
public ref class CefIdMappers sealed
16+
{
17+
public:
18+
static int CefIdForCommandIdName(String^ name);
19+
};
20+
}
21+
}

CefSharp.Core.Runtime/CefSharp.Core.Runtime.netcore.vcxproj

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -339,6 +339,7 @@
339339
</ItemDefinitionGroup>
340340
<ItemGroup>
341341
<ClCompile Include="AssemblyInfo.cpp" />
342+
<ClCompile Include="CefIdMappers.cpp" />
342343
<ClCompile Include="CookieManager.cpp" />
343344
<ClCompile Include="Internals\CefBrowserHostWrapper.cpp" />
344345
<ClCompile Include="Internals\CefContextMenuParamsWrapper.cpp" />
@@ -373,6 +374,7 @@
373374
<ItemGroup>
374375
<ClInclude Include="BrowserSettings.h" />
375376
<ClInclude Include="Cef.h" />
377+
<ClInclude Include="CefIdMappers.h" />
376378
<ClInclude Include="Internals\CefDevToolsMessageObserverAdapter.h" />
377379
<ClInclude Include="Internals\CefMediaAccessCallbackWrapper.h" />
378380
<ClInclude Include="Internals\CefPermissionPromptCallbackWrapper.h" />

CefSharp.Core.Runtime/CefSharp.Core.Runtime.netcore.vcxproj.filters

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,9 @@
8383
<ClCompile Include="Internals\CefRefCountManaged.cpp">
8484
<Filter>Source Files</Filter>
8585
</ClCompile>
86+
<ClCompile Include="CefIdMappers.cpp">
87+
<Filter>Source Files</Filter>
88+
</ClCompile>
8689
</ItemGroup>
8790
<ItemGroup>
8891
<ClInclude Include="vcclr_local.h">
@@ -325,6 +328,9 @@
325328
<ClInclude Include="Internals\CefTaskDelegate.h">
326329
<Filter>Header Files</Filter>
327330
</ClInclude>
331+
<ClInclude Include="CefIdMappers.h">
332+
<Filter>Header Files</Filter>
333+
</ClInclude>
328334
</ItemGroup>
329335
<ItemGroup>
330336
<ClInclude Include="Internals\CefFrameWrapper.h">

CefSharp.Core.Runtime/CefSharp.Core.Runtime.vcxproj

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -240,6 +240,7 @@
240240
</ItemGroup>
241241
<ItemGroup>
242242
<ClCompile Include="AssemblyInfo.cpp" />
243+
<ClCompile Include="CefIdMappers.cpp" />
243244
<ClCompile Include="CookieManager.cpp" />
244245
<ClCompile Include="Internals\CefBrowserHostWrapper.cpp" />
245246
<ClCompile Include="Internals\CefContextMenuParamsWrapper.cpp" />
@@ -272,6 +273,7 @@
272273
<ItemGroup>
273274
<ClInclude Include="BrowserSettings.h" />
274275
<ClInclude Include="Cef.h" />
276+
<ClInclude Include="CefIdMappers.h" />
275277
<ClInclude Include="DragData.h" />
276278
<ClInclude Include="Internals\CefDevToolsMessageObserverAdapter.h" />
277279
<ClInclude Include="Internals\CefMediaAccessCallbackWrapper.h" />

CefSharp.Core.Runtime/CefSharp.Core.Runtime.vcxproj.filters

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,9 @@
8383
<ClCompile Include="Internals\CefRefCountManaged.cpp">
8484
<Filter>Source Files</Filter>
8585
</ClCompile>
86+
<ClCompile Include="CefIdMappers.cpp">
87+
<Filter>Source Files</Filter>
88+
</ClCompile>
8689
</ItemGroup>
8790
<ItemGroup>
8891
<ClInclude Include="vcclr_local.h">
@@ -325,6 +328,9 @@
325328
<ClInclude Include="Internals\CefMediaAccessCallbackWrapper.h">
326329
<Filter>Header Files</Filter>
327330
</ClInclude>
331+
<ClInclude Include="CefIdMappers.h">
332+
<Filter>Header Files</Filter>
333+
</ClInclude>
328334
</ItemGroup>
329335
<ItemGroup>
330336
<ClInclude Include="Internals\CefFrameWrapper.h">

CefSharp.Core.Runtime/Internals/CefBrowserHostWrapper.cpp

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -639,6 +639,54 @@ void CefBrowserHostWrapper::SetAudioMuted(bool mute)
639639
_browserHost->SetAudioMuted(mute);
640640
}
641641

642+
bool CefBrowserHostWrapper::CanExecuteChromeCommand(int commandId)
643+
{
644+
ThrowIfDisposed();
645+
646+
if (CefCurrentlyOn(TID_UI))
647+
{
648+
return _browserHost->CanExecuteChromeCommand(commandId);
649+
}
650+
651+
throw gcnew InvalidOperationException("This method can only be called directly on the CEF UI Thread. Use CanExecuteChromeCommandAsync or use Cef.UIThreadTaskFactory to marshal the call onto the CEF UI Thread.");
652+
}
653+
654+
Task<bool>^ CefBrowserHostWrapper::CanExecuteChromeCommandAsync(int commandId)
655+
{
656+
ThrowIfDisposed();
657+
658+
if (CefCurrentlyOn(TID_UI))
659+
{
660+
return Task::FromResult(CanExecuteChromeCommandOnUI(commandId));
661+
}
662+
return Cef::UIThreadTaskFactory->StartNew(gcnew Func<Object^, bool>(this, &CefBrowserHostWrapper::CanExecuteChromeCommandOnUI), commandId);
663+
}
664+
665+
bool CefBrowserHostWrapper::CanExecuteChromeCommandOnUI(Object^ commandObject)
666+
{
667+
if (_disposed)
668+
{
669+
return false;
670+
}
671+
672+
CefTaskScheduler::EnsureOn(TID_UI, "CefBrowserHostWrapper::CanExecuteChromeCommand");
673+
674+
if (_browserHost.get())
675+
{
676+
int commandId = (int)commandObject;
677+
return _browserHost->CanExecuteChromeCommand(commandId);
678+
}
679+
680+
return false;
681+
}
682+
683+
void CefBrowserHostWrapper::ExecuteChromeCommand(int commandId, WindowOpenDisposition disposition)
684+
{
685+
ThrowIfDisposed();
686+
687+
_browserHost->ExecuteChromeCommand(commandId, (cef_window_open_disposition_t)disposition);
688+
}
689+
642690
IntPtr CefBrowserHostWrapper::GetOpenerWindowHandle()
643691
{
644692
ThrowIfDisposed();

CefSharp.Core.Runtime/Internals/CefBrowserHostWrapper.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ namespace CefSharp
2424
int _lastDevToolsMessageId = 0;
2525

2626
double GetZoomLevelOnUI();
27+
bool CanExecuteChromeCommandOnUI(Object^ commandObject);
2728

2829
internal:
2930
CefBrowserHostWrapper(const CefRefPtr<CefBrowserHost> &browserHost) : _browserHost(browserHost)
@@ -140,6 +141,12 @@ namespace CefSharp
140141

141142
virtual void SetAudioMuted(bool mute);
142143

144+
virtual bool CanExecuteChromeCommand(int commandId);
145+
146+
virtual Task<bool>^ CanExecuteChromeCommandAsync(int commandId);
147+
148+
virtual void ExecuteChromeCommand(int commandId, WindowOpenDisposition disposition);
149+
143150
virtual IntPtr GetOpenerWindowHandle();
144151

145152
virtual void SendExternalBeginFrame();

CefSharp.Core/CefIdMappers.cs

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
// Copyright © 2026 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+
namespace CefSharp
6+
{
7+
/// <summary>
8+
/// Provides version-safe mapping of Chromium string identifiers to their version-specific numeric ID values.
9+
/// </summary>
10+
public static class CefIdMappers
11+
{
12+
/// <summary>
13+
/// Returns the numeric ID value for an IDC <paramref name="name"/> from cef_command_ids.h or -1
14+
/// if <paramref name="name"/> is unrecognized by the current CEF/Chromium build.
15+
/// </summary>
16+
/// <remarks>
17+
/// This function provides version-safe mapping of command IDC names to version-specific
18+
/// numeric ID values. Numeric ID values are likely to change across
19+
/// CEF/Chromium versions but names generally remain the same.
20+
/// </remarks>
21+
/// <param name="name">String identifier of the Chromium command.</param>
22+
/// <returns>version-specific numeric ID value for the command if recognized; otherwise, -1.</returns>
23+
public static int CefIdForCommandIdName(string name)
24+
{
25+
return CefSharp.Core.CefIdMappers.CefIdForCommandIdName(name);
26+
}
27+
}
28+
}

CefSharp/IBrowserHost.cs

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -502,6 +502,29 @@ public interface IBrowserHost : IDisposable
502502
/// <param name="mute">true or false</param>
503503
void SetAudioMuted(bool mute);
504504

505+
/// <summary>
506+
/// Returns true if a Chrome command is supported and enabled. This method can only be called on the CEF UI thread. Only
507+
/// used with Chrome style.
508+
/// </summary>
509+
/// <param name="commandId">command id</param>
510+
/// <returns>availability of the Chrome command.</returns>
511+
bool CanExecuteChromeCommand(int commandId);
512+
513+
/// <summary>
514+
/// Returns true if a Chrome command is supported and enabled. This method executes CanExecuteChromeCommand on the CEF UI thread
515+
/// in an async fashion. Only used with Chrome style.
516+
/// </summary>
517+
/// <param name="commandId">command id</param>
518+
/// <returns> a <see cref="Task{Boolean}"/> that when executed returns the availability of the Chrome command as a boolean.</returns>
519+
Task<bool> CanExecuteChromeCommandAsync(int commandId);
520+
521+
/// <summary>
522+
/// Execute a Chrome command. Only used with Chrome style.
523+
/// </summary>
524+
/// <param name="commandId">command id</param>
525+
/// <param name="disposition">command target</param>
526+
void ExecuteChromeCommand(int commandId, WindowOpenDisposition disposition);
527+
505528
/// <summary>
506529
/// Returns true if the browser's audio is muted.
507530
/// This method can only be called on the CEF UI thread.

0 commit comments

Comments
 (0)