diff --git a/MR-DESCRIPTION.md b/MR-DESCRIPTION.md
new file mode 100644
index 0000000..58077a5
--- /dev/null
+++ b/MR-DESCRIPTION.md
@@ -0,0 +1,50 @@
+# feat: expose client delegate hooks required by embedding hosts
+
+## Summary
+
+Adds four virtual hooks to `CefViewBrowserClientDelegate` that embedding
+hosts currently have no way to observe. All have default implementations
+and are purely additive — no existing override changes behavior.
+
+| Hook | Before | After |
+|---|---|---|
+| `onBeforeBrowse` | dropped after `message_router_->OnBeforeBrowse` | forwarded; return true cancels |
+| `onRenderProcessTerminated` | dropped after message-router cleanup (TerminationStatus already scoped) | forwarded with status/error_code/error_string (CEF 124+; two-arg overload otherwise) |
+| `onFindResult` | **result discarded entirely** (empty `OnFindResult` body) | forwarded with identifier/count/selectionRect/activeMatchOrdinal/finalUpdate |
+| `onFileDialogEx` | — (CEF 126+ accept extensions/descriptions unavailable) | new; default falls back to `onFileDialog`, so existing subclasses are unaffected |
+
+## Why these four
+
+- **onBeforeBrowse** is the only interception point for in-page navigations,
+ redirects, iframes and `window.open` — an embedding host cannot implement a
+ navigation policy without it.
+- **onRenderProcessTerminated** is the renderer-crash observability hook
+ (host-level auto-reload / telemetry).
+- **onFindResult** powers find-in-page UI; the current code receives the
+ callback and drops it.
+- **onFileDialogEx** exposes the accept extensions/descriptions CEF 126+
+ provides; the legacy `onFileDialog` cannot carry them.
+
+## Compatibility
+
+- Default implementations only: overriding none of them is byte-for-byte
+ the previous behavior (verified: consumers that don't override compile and
+ run identically).
+- `onFileDialogEx` guards `CEF_VERSION_MAJOR >= 126`; `onRenderProcessTerminated`
+ keeps a two-arg overload path for CEF < 124.
+- No ABI change to existing symbols; `CefVersion.h` pin in this branch is a
+ local-baseline concern (drop that commit when merging — it reflects this
+ fork's 127.3.5 rollback, not an upstream recommendation).
+
+## Validation
+
+Downstream consumer (Unity embedding, private) runs these hooks through a
+pfn callback ABI with machine-verified regressions:
+- navigation-policy rejections observable end-to-end (`javascript:` scheme
+ blocked, machine-readable reasons)
+- renderer kill injection → host receives termination + auto-reload
+- find results streamed to a host UI
+- file dialog extensions/descriptions cross the ABI as JSON
+
+Branch: `feat/unity-callbacks` (5 commits; the `CefVersion.h` pin commit
+`0bba10b` is fork-local and should be excluded from the merge).
diff --git a/include/CefVersion.h b/include/CefVersion.h
index 1f20f07..da85c65 100644
--- a/include/CefVersion.h
+++ b/include/CefVersion.h
@@ -13,12 +13,12 @@
#pragma once
// clang-format off
-#define CEF_VERSION "142.0.15+g6dfdb28+chromium-142.0.7444.176"
-#define CEF_VERSION_MAJOR 142
-#define CEF_VERSION_MINOR 0
-#define CEF_VERSION_PATCH 15
-#define CEF_COMMIT_NUMBER 3314
-#define CEF_COMMIT_HASH "6dfdb28d752a47e189d7a23b01f368ab0bdb378d"
+#define CEF_VERSION "127.3.5+g114ea2a+chromium-127.0.6533.120"
+#define CEF_VERSION_MAJOR 127
+#define CEF_VERSION_MINOR 3
+#define CEF_VERSION_PATCH 5
+#define CEF_COMMIT_NUMBER 3037
+#define CEF_COMMIT_HASH "114ea2af1ba9da18c4ac5e599ccdbb17d01ba75a"
// clang-format on
#endif // CefVersion
diff --git a/include/CefViewBrowserClientDelegate.h b/include/CefViewBrowserClientDelegate.h
index 38b4889..9f3d0da 100644
--- a/include/CefViewBrowserClientDelegate.h
+++ b/include/CefViewBrowserClientDelegate.h
@@ -123,6 +123,25 @@ class CefViewBrowserClientDelegateInterface
{
return false;
};
+
+#if CEF_VERSION_MAJOR >= 126
+ ///
+ /// Same as onFileDialog plus the raw accept extensions and descriptions
+ /// that CEF 126+ provides. The default implementation discards the extra
+ /// information and falls back to onFileDialog.
+ ///
+ virtual bool onFileDialogEx(CefRefPtr& browser,
+ CefBrowserHost::FileDialogMode mode,
+ const CefString& title,
+ const CefString& default_file_path,
+ const std::vector& accept_filters,
+ const std::vector& accept_extensions,
+ const std::vector& accept_descriptions,
+ CefRefPtr& callback)
+ {
+ return onFileDialog(browser, mode, title, default_file_path, accept_filters, callback);
+ }
+#endif
#pragma endregion
// display handler
@@ -175,6 +194,27 @@ class CefViewBrowserClientDelegateInterface
const std::vector& regions) = 0;
#pragma endregion
+ // find handler
+#pragma region FindHandler
+ ///
+ /// Called to report find results.
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ virtual void onFindResult(CefRefPtr& browser,
+ int identifier,
+ int count,
+ const CefRect& selectionRect,
+ int activeMatchOrdinal,
+ bool finalUpdate)
+ {
+ }
+#pragma endregion
+
// focus handler
#pragma region FocusHandler
virtual void takeFocus(CefRefPtr& browser, bool next) = 0;
@@ -252,6 +292,40 @@ class CefViewBrowserClientDelegateInterface
bool& handled) = 0;
#pragma endregion
+ // request handler
+#pragma region RequestHandler
+ ///
+ /// Called on the UI thread before browser navigation.
+ /// Return true to cancel the navigation.
+ ///
+ virtual bool onBeforeBrowse(CefRefPtr& browser,
+ CefRefPtr& frame,
+ CefRefPtr& request,
+ bool user_gesture,
+ bool is_redirect)
+ {
+ return false;
+ }
+
+ ///
+ /// Called when the render process terminates abnormally.
+ ///
+ ///
+ ///
+ /// Only available for CEF 124 and above.
+ /// Only available for CEF 124 and above.
+ virtual void onRenderProcessTerminated(CefRefPtr& browser,
+ CefRequestHandler::TerminationStatus status
+#if CEF_VERSION_MAJOR >= 124
+ ,
+ int errorCode,
+ const CefString& errorString
+#endif
+ )
+ {
+ }
+#pragma endregion
+
#if CEF_VERSION_MAJOR >= 106
#pragma region PermissionHandler
virtual bool onRequestMediaAccessPermission(CefRefPtr& browser,
diff --git a/src/CefView/CefBrowserApp/CefViewBrowserClient_DialogHandler.cpp b/src/CefView/CefBrowserApp/CefViewBrowserClient_DialogHandler.cpp
index 86bc04c..edc25eb 100644
--- a/src/CefView/CefBrowserApp/CefViewBrowserClient_DialogHandler.cpp
+++ b/src/CefView/CefBrowserApp/CefViewBrowserClient_DialogHandler.cpp
@@ -44,7 +44,17 @@ CefViewBrowserClient::OnFileDialog(CefRefPtr browser,
#endif
{
auto delegate = client_delegate_.lock();
- if (delegate)
+ if (delegate) {
+#if CEF_VERSION_MAJOR >= 126
+ return delegate->onFileDialogEx(browser,
+ mode,
+ title,
+ default_file_path,
+ accept_filters,
+ accept_extensions,
+ accept_descriptions,
+ callback);
+#else
return delegate->onFileDialog(browser,
mode,
title,
@@ -54,6 +64,8 @@ CefViewBrowserClient::OnFileDialog(CefRefPtr browser,
selected_accept_filter,
#endif
callback);
+#endif
+ }
return false;
}
diff --git a/src/CefView/CefBrowserApp/CefViewBrowserClient_FindHandler.cpp b/src/CefView/CefBrowserApp/CefViewBrowserClient_FindHandler.cpp
index 4f3d788..f401814 100644
--- a/src/CefView/CefBrowserApp/CefViewBrowserClient_FindHandler.cpp
+++ b/src/CefView/CefBrowserApp/CefViewBrowserClient_FindHandler.cpp
@@ -17,4 +17,7 @@ CefViewBrowserClient::OnFindResult(CefRefPtr browser,
bool finalUpdate)
{
CEF_REQUIRE_UI_THREAD();
+
+ if (auto delegate = client_delegate_.lock())
+ delegate->onFindResult(browser, identifier, count, selectionRect, activeMatchOrdinal, finalUpdate);
}
diff --git a/src/CefView/CefBrowserApp/CefViewBrowserClient_RequestHandler.cpp b/src/CefView/CefBrowserApp/CefViewBrowserClient_RequestHandler.cpp
index 741c40d..a16287c 100644
--- a/src/CefView/CefBrowserApp/CefViewBrowserClient_RequestHandler.cpp
+++ b/src/CefView/CefBrowserApp/CefViewBrowserClient_RequestHandler.cpp
@@ -24,6 +24,10 @@ CefViewBrowserClient::OnBeforeBrowse(CefRefPtr browser,
CEF_REQUIRE_UI_THREAD();
message_router_->OnBeforeBrowse(browser, frame);
+
+ if (auto delegate = client_delegate_.lock())
+ return delegate->onBeforeBrowse(browser, frame, request, user_gesture, is_redirect);
+
return false;
}
@@ -72,6 +76,14 @@ CefViewBrowserClient::OnRenderProcessTerminated(CefRefPtr browser,
message_router_->OnRenderProcessTerminated(browser);
+ if (auto delegate = client_delegate_.lock()) {
+#if CEF_VERSION_MAJOR >= 124
+ delegate->onRenderProcessTerminated(browser, status, error_code, error_string);
+#else
+ delegate->onRenderProcessTerminated(browser, status);
+#endif
+ }
+
if (browser) {
CefString url = browser->GetMainFrame()->GetURL();
if (!url.empty()) {