cefclient: Fix invalid cast to ClientHandlerStd (see #3499)

This commit is contained in:
Marshall Greenblatt 2024-08-05 18:30:39 -04:00
parent f6f4ba8317
commit 166eec85e0
13 changed files with 95 additions and 7 deletions

View File

@ -245,6 +245,7 @@
'tests/cefclient/browser/client_prefs.cc', 'tests/cefclient/browser/client_prefs.cc',
'tests/cefclient/browser/client_prefs.h', 'tests/cefclient/browser/client_prefs.h',
'tests/cefclient/browser/client_types.h', 'tests/cefclient/browser/client_types.h',
'tests/cefclient/browser/default_client_handler.cc',
'tests/cefclient/browser/default_client_handler.h', 'tests/cefclient/browser/default_client_handler.h',
'tests/cefclient/browser/dialog_test.cc', 'tests/cefclient/browser/dialog_test.cc',
'tests/cefclient/browser/dialog_test.h', 'tests/cefclient/browser/dialog_test.h',

View File

@ -14,7 +14,13 @@ BaseClientHandler::BaseClientHandler() {
// static // static
CefRefPtr<BaseClientHandler> BaseClientHandler::GetForBrowser( CefRefPtr<BaseClientHandler> BaseClientHandler::GetForBrowser(
CefRefPtr<CefBrowser> browser) { CefRefPtr<CefBrowser> browser) {
return static_cast<BaseClientHandler*>(browser->GetHost()->GetClient().get()); return GetForClient(browser->GetHost()->GetClient());
}
// static
CefRefPtr<BaseClientHandler> BaseClientHandler::GetForClient(
CefRefPtr<CefClient> client) {
return static_cast<BaseClientHandler*>(client.get());
} }
bool BaseClientHandler::OnProcessMessageReceived( bool BaseClientHandler::OnProcessMessageReceived(

View File

@ -24,6 +24,9 @@ class BaseClientHandler : public CefClient,
static CefRefPtr<BaseClientHandler> GetForBrowser( static CefRefPtr<BaseClientHandler> GetForBrowser(
CefRefPtr<CefBrowser> browser); CefRefPtr<CefBrowser> browser);
// Returns the BaseClientHandler for |client|.
static CefRefPtr<BaseClientHandler> GetForClient(CefRefPtr<CefClient> client);
// CefClient methods // CefClient methods
CefRefPtr<CefLifeSpanHandler> GetLifeSpanHandler() override { return this; } CefRefPtr<CefLifeSpanHandler> GetLifeSpanHandler() override { return this; }
CefRefPtr<CefRequestHandler> GetRequestHandler() override { return this; } CefRefPtr<CefRequestHandler> GetRequestHandler() override { return this; }
@ -92,6 +95,9 @@ class BaseClientHandler : public CefClient,
void SetHangAction(HangAction action); void SetHangAction(HangAction action);
HangAction GetHangAction() const; HangAction GetHangAction() const;
// Used to determine the object type for each concrete implementation.
virtual const void* GetTypeKey() const = 0;
protected: protected:
CefRefPtr<CefResourceManager> GetResourceManager() const { CefRefPtr<CefResourceManager> GetResourceManager() const {
return resource_manager_; return resource_manager_;

View File

@ -1124,7 +1124,9 @@ void BrowserWindowOsrGtk::OnBeforeClose(CefRefPtr<CefBrowser> browser) {
CEF_REQUIRE_UI_THREAD(); CEF_REQUIRE_UI_THREAD();
// Detach |this| from the ClientHandlerOsr. // Detach |this| from the ClientHandlerOsr.
static_cast<ClientHandlerOsr*>(client_handler_.get())->DetachOsrDelegate(); auto handler = ClientHandlerOsr::GetForClient(client_handler_);
CHECK(handler);
handler->DetachOsrDelegate();
ScopedGdkThreadsEnter scoped_gdk_threads; ScopedGdkThreadsEnter scoped_gdk_threads;

View File

@ -1581,8 +1581,10 @@ void BrowserWindowOsrMacImpl::OnBeforeClose(CefRefPtr<CefBrowser> browser) {
REQUIRE_MAIN_THREAD(); REQUIRE_MAIN_THREAD();
// Detach |this| from the ClientHandlerOsr. // Detach |this| from the ClientHandlerOsr.
static_cast<ClientHandlerOsr*>(browser_window_.client_handler_.get()) auto handler =
->DetachOsrDelegate(); ClientHandlerOsr::GetForClient(browser_window_.client_handler_);
CHECK(handler);
handler->DetachOsrDelegate();
} }
bool BrowserWindowOsrMacImpl::GetRootScreenRect(CefRefPtr<CefBrowser> browser, bool BrowserWindowOsrMacImpl::GetRootScreenRect(CefRefPtr<CefBrowser> browser,

View File

@ -19,6 +19,16 @@ ClientHandlerOsr::ClientHandlerOsr(Delegate* delegate,
DCHECK(osr_delegate_); DCHECK(osr_delegate_);
} }
// static
CefRefPtr<ClientHandlerOsr> ClientHandlerOsr::GetForClient(
CefRefPtr<CefClient> client) {
auto base = BaseClientHandler::GetForClient(client);
if (base && base->GetTypeKey() == &kTypeKey) {
return static_cast<ClientHandlerOsr*>(base.get());
}
return nullptr;
}
void ClientHandlerOsr::DetachOsrDelegate() { void ClientHandlerOsr::DetachOsrDelegate() {
if (!CefCurrentlyOn(TID_UI)) { if (!CefCurrentlyOn(TID_UI)) {
// Execute this method on the UI thread. // Execute this method on the UI thread.

View File

@ -80,6 +80,10 @@ class ClientHandlerOsr : public ClientHandler,
bool with_controls, bool with_controls,
const std::string& startup_url); const std::string& startup_url);
// Returns the ClientHandlerOsr for |client|, or nullptr if |client| is not a
// ClientHandlerOsr.
static CefRefPtr<ClientHandlerOsr> GetForClient(CefRefPtr<CefClient> client);
// This object may outlive the OsrDelegate object so it's necessary for the // This object may outlive the OsrDelegate object so it's necessary for the
// OsrDelegate to detach itself before destruction. // OsrDelegate to detach itself before destruction.
void DetachOsrDelegate(); void DetachOsrDelegate();
@ -139,6 +143,10 @@ class ClientHandlerOsr : public ClientHandler,
void OnAccessibilityLocationChange(CefRefPtr<CefValue> value) override; void OnAccessibilityLocationChange(CefRefPtr<CefValue> value) override;
private: 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. // Only accessed on the UI thread.
OsrDelegate* osr_delegate_; OsrDelegate* osr_delegate_;

View File

@ -11,4 +11,14 @@ ClientHandlerStd::ClientHandlerStd(Delegate* delegate,
const std::string& startup_url) const std::string& startup_url)
: ClientHandler(delegate, /*is_osr=*/false, with_controls, startup_url) {} : ClientHandler(delegate, /*is_osr=*/false, with_controls, startup_url) {}
// static
CefRefPtr<ClientHandlerStd> ClientHandlerStd::GetForClient(
CefRefPtr<CefClient> client) {
auto base = BaseClientHandler::GetForClient(client);
if (base && base->GetTypeKey() == &kTypeKey) {
return static_cast<ClientHandlerStd*>(base.get());
}
return nullptr;
}
} // namespace client } // namespace client

View File

@ -18,7 +18,15 @@ class ClientHandlerStd : public ClientHandler {
bool with_controls, bool with_controls,
const std::string& startup_url); const std::string& startup_url);
// Returns the ClientHandlerStd for |client|, or nullptr if |client| is not a
// ClientHandlerStd.
static CefRefPtr<ClientHandlerStd> GetForClient(CefRefPtr<CefClient> client);
private: 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. // Include the default reference counting implementation.
IMPLEMENT_REFCOUNTING(ClientHandlerStd); IMPLEMENT_REFCOUNTING(ClientHandlerStd);
DISALLOW_COPY_AND_ASSIGN(ClientHandlerStd); DISALLOW_COPY_AND_ASSIGN(ClientHandlerStd);

View File

@ -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> DefaultClientHandler::GetForClient(
CefRefPtr<CefClient> client) {
auto base = BaseClientHandler::GetForClient(client);
if (base && base->GetTypeKey() == &kTypeKey) {
return static_cast<DefaultClientHandler*>(base.get());
}
return nullptr;
}
} // namespace client

View File

@ -16,7 +16,16 @@ class DefaultClientHandler : public BaseClientHandler {
public: public:
DefaultClientHandler() = default; DefaultClientHandler() = default;
// Returns the DefaultClientHandler for |client|, or nullptr if |client| is
// not a DefaultClientHandler.
static CefRefPtr<DefaultClientHandler> GetForClient(
CefRefPtr<CefClient> client);
private: private:
// Used to determine the object type.
virtual const void* GetTypeKey() const override { return &kTypeKey; }
static const int kTypeKey = 0;
IMPLEMENT_REFCOUNTING(DefaultClientHandler); IMPLEMENT_REFCOUNTING(DefaultClientHandler);
DISALLOW_COPY_AND_ASSIGN(DefaultClientHandler); DISALLOW_COPY_AND_ASSIGN(DefaultClientHandler);
}; };

View File

@ -947,8 +947,10 @@ void OsrWindowWin::OnAfterCreated(CefRefPtr<CefBrowser> browser) {
void OsrWindowWin::OnBeforeClose(CefRefPtr<CefBrowser> browser) { void OsrWindowWin::OnBeforeClose(CefRefPtr<CefBrowser> browser) {
CEF_REQUIRE_UI_THREAD(); CEF_REQUIRE_UI_THREAD();
// Detach |this| from the ClientHandlerOsr. // Detach |this| from the ClientHandlerOsr.
static_cast<ClientHandlerOsr*>(browser_->GetHost()->GetClient().get()) auto handler =
->DetachOsrDelegate(); ClientHandlerOsr::GetForClient(browser_->GetHost()->GetClient());
CHECK(handler);
handler->DetachOsrDelegate();
browser_ = nullptr; browser_ = nullptr;
render_handler_->SetBrowser(nullptr); render_handler_->SetBrowser(nullptr);
Destroy(); Destroy();

View File

@ -273,7 +273,12 @@ ViewsWindow::Delegate* RootWindowViews::GetDelegateForPopup(
CefRefPtr<CefClient> client) { CefRefPtr<CefClient> client) {
CEF_REQUIRE_UI_THREAD(); CEF_REQUIRE_UI_THREAD();
// |handler| was created in RootWindowViews::InitAsPopup(). // |handler| was created in RootWindowViews::InitAsPopup().
ClientHandlerStd* handler = static_cast<ClientHandlerStd*>(client.get()); // May return nullptr when running with `--use-default-popup`.
auto handler = ClientHandlerStd::GetForClient(client);
if (!handler) {
return nullptr;
}
RootWindowViews* root_window = RootWindowViews* root_window =
static_cast<RootWindowViews*>(handler->delegate()); static_cast<RootWindowViews*>(handler->delegate());