From 166eec85e05e27eaaed6f0f8dfe4276793f473d1 Mon Sep 17 00:00:00 2001 From: Marshall Greenblatt Date: Mon, 5 Aug 2024 18:30:39 -0400 Subject: [PATCH] cefclient: Fix invalid cast to ClientHandlerStd (see #3499) --- cef_paths2.gypi | 1 + .../cefclient/browser/base_client_handler.cc | 8 +++++++- tests/cefclient/browser/base_client_handler.h | 6 ++++++ .../browser/browser_window_osr_gtk.cc | 4 +++- .../browser/browser_window_osr_mac.mm | 6 ++++-- tests/cefclient/browser/client_handler_osr.cc | 10 ++++++++++ tests/cefclient/browser/client_handler_osr.h | 8 ++++++++ tests/cefclient/browser/client_handler_std.cc | 10 ++++++++++ tests/cefclient/browser/client_handler_std.h | 8 ++++++++ .../browser/default_client_handler.cc | 19 +++++++++++++++++++ .../browser/default_client_handler.h | 9 +++++++++ tests/cefclient/browser/osr_window_win.cc | 6 ++++-- tests/cefclient/browser/root_window_views.cc | 7 ++++++- 13 files changed, 95 insertions(+), 7 deletions(-) create mode 100644 tests/cefclient/browser/default_client_handler.cc diff --git a/cef_paths2.gypi b/cef_paths2.gypi index 837d70071..0cf1e4475 100644 --- a/cef_paths2.gypi +++ b/cef_paths2.gypi @@ -245,6 +245,7 @@ 'tests/cefclient/browser/client_prefs.cc', 'tests/cefclient/browser/client_prefs.h', 'tests/cefclient/browser/client_types.h', + 'tests/cefclient/browser/default_client_handler.cc', 'tests/cefclient/browser/default_client_handler.h', 'tests/cefclient/browser/dialog_test.cc', 'tests/cefclient/browser/dialog_test.h', diff --git a/tests/cefclient/browser/base_client_handler.cc b/tests/cefclient/browser/base_client_handler.cc index 9832cce1d..49d93447c 100644 --- a/tests/cefclient/browser/base_client_handler.cc +++ b/tests/cefclient/browser/base_client_handler.cc @@ -14,7 +14,13 @@ BaseClientHandler::BaseClientHandler() { // static CefRefPtr BaseClientHandler::GetForBrowser( CefRefPtr browser) { - return static_cast(browser->GetHost()->GetClient().get()); + return GetForClient(browser->GetHost()->GetClient()); +} + +// static +CefRefPtr BaseClientHandler::GetForClient( + CefRefPtr client) { + return static_cast(client.get()); } bool BaseClientHandler::OnProcessMessageReceived( diff --git a/tests/cefclient/browser/base_client_handler.h b/tests/cefclient/browser/base_client_handler.h index e811c03dc..6f5eba882 100644 --- a/tests/cefclient/browser/base_client_handler.h +++ b/tests/cefclient/browser/base_client_handler.h @@ -24,6 +24,9 @@ class BaseClientHandler : public CefClient, static CefRefPtr GetForBrowser( CefRefPtr browser); + // Returns the BaseClientHandler for |client|. + static CefRefPtr GetForClient(CefRefPtr client); + // CefClient methods CefRefPtr GetLifeSpanHandler() override { return this; } CefRefPtr GetRequestHandler() override { return this; } @@ -92,6 +95,9 @@ class BaseClientHandler : public CefClient, void SetHangAction(HangAction action); HangAction GetHangAction() const; + // Used to determine the object type for each concrete implementation. + virtual const void* GetTypeKey() const = 0; + protected: CefRefPtr GetResourceManager() const { return resource_manager_; diff --git a/tests/cefclient/browser/browser_window_osr_gtk.cc b/tests/cefclient/browser/browser_window_osr_gtk.cc index aafbd8418..132f4fcd1 100644 --- a/tests/cefclient/browser/browser_window_osr_gtk.cc +++ b/tests/cefclient/browser/browser_window_osr_gtk.cc @@ -1124,7 +1124,9 @@ void BrowserWindowOsrGtk::OnBeforeClose(CefRefPtr browser) { CEF_REQUIRE_UI_THREAD(); // Detach |this| from the ClientHandlerOsr. - static_cast(client_handler_.get())->DetachOsrDelegate(); + auto handler = ClientHandlerOsr::GetForClient(client_handler_); + CHECK(handler); + handler->DetachOsrDelegate(); ScopedGdkThreadsEnter scoped_gdk_threads; diff --git a/tests/cefclient/browser/browser_window_osr_mac.mm b/tests/cefclient/browser/browser_window_osr_mac.mm index 511f0a1e1..dc0b7ac79 100644 --- a/tests/cefclient/browser/browser_window_osr_mac.mm +++ b/tests/cefclient/browser/browser_window_osr_mac.mm @@ -1581,8 +1581,10 @@ void BrowserWindowOsrMacImpl::OnBeforeClose(CefRefPtr browser) { REQUIRE_MAIN_THREAD(); // Detach |this| from the ClientHandlerOsr. - static_cast(browser_window_.client_handler_.get()) - ->DetachOsrDelegate(); + auto handler = + ClientHandlerOsr::GetForClient(browser_window_.client_handler_); + CHECK(handler); + handler->DetachOsrDelegate(); } bool BrowserWindowOsrMacImpl::GetRootScreenRect(CefRefPtr browser, diff --git a/tests/cefclient/browser/client_handler_osr.cc b/tests/cefclient/browser/client_handler_osr.cc index 27e8125b8..667e22063 100644 --- a/tests/cefclient/browser/client_handler_osr.cc +++ b/tests/cefclient/browser/client_handler_osr.cc @@ -19,6 +19,16 @@ ClientHandlerOsr::ClientHandlerOsr(Delegate* delegate, DCHECK(osr_delegate_); } +// static +CefRefPtr ClientHandlerOsr::GetForClient( + CefRefPtr client) { + auto base = BaseClientHandler::GetForClient(client); + if (base && base->GetTypeKey() == &kTypeKey) { + return static_cast(base.get()); + } + return nullptr; +} + void ClientHandlerOsr::DetachOsrDelegate() { if (!CefCurrentlyOn(TID_UI)) { // Execute this method on the UI thread. diff --git a/tests/cefclient/browser/client_handler_osr.h b/tests/cefclient/browser/client_handler_osr.h index 8d748ea38..a8976873f 100644 --- a/tests/cefclient/browser/client_handler_osr.h +++ b/tests/cefclient/browser/client_handler_osr.h @@ -80,6 +80,10 @@ class ClientHandlerOsr : public ClientHandler, bool with_controls, const std::string& startup_url); + // Returns the ClientHandlerOsr for |client|, or nullptr if |client| is not a + // ClientHandlerOsr. + static CefRefPtr GetForClient(CefRefPtr client); + // This object may outlive the OsrDelegate object so it's necessary for the // OsrDelegate to detach itself before destruction. void DetachOsrDelegate(); @@ -139,6 +143,10 @@ class ClientHandlerOsr : public ClientHandler, void OnAccessibilityLocationChange(CefRefPtr value) override; private: + // Used to determine the object type. + virtual const void* GetTypeKey() const override { return &kTypeKey; } + static const int kTypeKey = 0; + // Only accessed on the UI thread. OsrDelegate* osr_delegate_; diff --git a/tests/cefclient/browser/client_handler_std.cc b/tests/cefclient/browser/client_handler_std.cc index e78166d93..a8dbc035b 100644 --- a/tests/cefclient/browser/client_handler_std.cc +++ b/tests/cefclient/browser/client_handler_std.cc @@ -11,4 +11,14 @@ ClientHandlerStd::ClientHandlerStd(Delegate* delegate, const std::string& startup_url) : ClientHandler(delegate, /*is_osr=*/false, with_controls, startup_url) {} +// static +CefRefPtr ClientHandlerStd::GetForClient( + CefRefPtr client) { + auto base = BaseClientHandler::GetForClient(client); + if (base && base->GetTypeKey() == &kTypeKey) { + return static_cast(base.get()); + } + return nullptr; +} + } // namespace client diff --git a/tests/cefclient/browser/client_handler_std.h b/tests/cefclient/browser/client_handler_std.h index 02aa74767..f589824b3 100644 --- a/tests/cefclient/browser/client_handler_std.h +++ b/tests/cefclient/browser/client_handler_std.h @@ -18,7 +18,15 @@ class ClientHandlerStd : public ClientHandler { bool with_controls, const std::string& startup_url); + // Returns the ClientHandlerStd for |client|, or nullptr if |client| is not a + // ClientHandlerStd. + static CefRefPtr GetForClient(CefRefPtr client); + private: + // Used to determine the object type. + virtual const void* GetTypeKey() const override { return &kTypeKey; } + static const int kTypeKey = 0; + // Include the default reference counting implementation. IMPLEMENT_REFCOUNTING(ClientHandlerStd); DISALLOW_COPY_AND_ASSIGN(ClientHandlerStd); diff --git a/tests/cefclient/browser/default_client_handler.cc b/tests/cefclient/browser/default_client_handler.cc new file mode 100644 index 000000000..21cc38c00 --- /dev/null +++ b/tests/cefclient/browser/default_client_handler.cc @@ -0,0 +1,19 @@ +// Copyright (c) 2024 The Chromium Embedded Framework 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 "tests/cefclient/browser/default_client_handler.h" + +namespace client { + +// static +CefRefPtr DefaultClientHandler::GetForClient( + CefRefPtr client) { + auto base = BaseClientHandler::GetForClient(client); + if (base && base->GetTypeKey() == &kTypeKey) { + return static_cast(base.get()); + } + return nullptr; +} + +} // namespace client diff --git a/tests/cefclient/browser/default_client_handler.h b/tests/cefclient/browser/default_client_handler.h index 678ac899a..371988b21 100644 --- a/tests/cefclient/browser/default_client_handler.h +++ b/tests/cefclient/browser/default_client_handler.h @@ -16,7 +16,16 @@ class DefaultClientHandler : public BaseClientHandler { public: DefaultClientHandler() = default; + // Returns the DefaultClientHandler for |client|, or nullptr if |client| is + // not a DefaultClientHandler. + static CefRefPtr GetForClient( + CefRefPtr client); + private: + // Used to determine the object type. + virtual const void* GetTypeKey() const override { return &kTypeKey; } + static const int kTypeKey = 0; + IMPLEMENT_REFCOUNTING(DefaultClientHandler); DISALLOW_COPY_AND_ASSIGN(DefaultClientHandler); }; diff --git a/tests/cefclient/browser/osr_window_win.cc b/tests/cefclient/browser/osr_window_win.cc index 38085e630..75db8fc4b 100644 --- a/tests/cefclient/browser/osr_window_win.cc +++ b/tests/cefclient/browser/osr_window_win.cc @@ -947,8 +947,10 @@ void OsrWindowWin::OnAfterCreated(CefRefPtr browser) { void OsrWindowWin::OnBeforeClose(CefRefPtr browser) { CEF_REQUIRE_UI_THREAD(); // Detach |this| from the ClientHandlerOsr. - static_cast(browser_->GetHost()->GetClient().get()) - ->DetachOsrDelegate(); + auto handler = + ClientHandlerOsr::GetForClient(browser_->GetHost()->GetClient()); + CHECK(handler); + handler->DetachOsrDelegate(); browser_ = nullptr; render_handler_->SetBrowser(nullptr); Destroy(); diff --git a/tests/cefclient/browser/root_window_views.cc b/tests/cefclient/browser/root_window_views.cc index 276a78fa0..5a9f856ee 100644 --- a/tests/cefclient/browser/root_window_views.cc +++ b/tests/cefclient/browser/root_window_views.cc @@ -273,7 +273,12 @@ ViewsWindow::Delegate* RootWindowViews::GetDelegateForPopup( CefRefPtr client) { CEF_REQUIRE_UI_THREAD(); // |handler| was created in RootWindowViews::InitAsPopup(). - ClientHandlerStd* handler = static_cast(client.get()); + // May return nullptr when running with `--use-default-popup`. + auto handler = ClientHandlerStd::GetForClient(client); + if (!handler) { + return nullptr; + } + RootWindowViews* root_window = static_cast(handler->delegate());