Usage of m_cefBrowser->GetHost()->SetFocus

Having problems with building or using CEF's C/C++ APIs? This forum is here to help. Please do not post bug reports or feature requests here.

Usage of m_cefBrowser->GetHost()->SetFocus

Postby ctrebs » Wed Jul 20, 2022 2:42 pm

We are upgrading our application to use a newer version of CEF, and hitting a sporadic exception in CefBrowserPlatformDelegateNativeWin::SetFocus.

platform: Windows 32
OS: Windows 10

previous version of CEF:
02/16/2017 - 3.2924.1570.g558741c / Chromium 56.0.2924.76

upgrade version of CEF:
01/15/2022 - 97.1.5+g2b00258+chromium-97.0.4692.71 / Chromium 97.0.4692.71


We call m_cefBrowser->GetHost()->SetFocus as shown below (from the window that owns the browser)

Code: Select all
   ON_WM_SETFOCUS()
   ON_WM_KILLFOCUS()

END_MESSAGE_MAP()

CER_VOID
CER_PANEL_CEFB::OnSetFocus(PCWnd ppcLastFocus)
{
   if (m_cefBrowser)
   {
      if (CefCurrentlyOn(TID_UI))
         m_cefBrowser->GetHost()->SetFocus(true);
   }
}

CER_VOID
CER_PANEL_CEFB::OnKillFocus(PCWnd ppcLastFocus)
{
   if (m_cefBrowser)
   {
      if (CefCurrentlyOn(TID_UI))
         m_cefBrowser->GetHost()->SetFocus(false);
   }
}



Occassionally, we hit a nullptr exception in the call to ::SetFocus(HWNDForWidget(window_widget_) in the code below.

Exception:
Unhandled exception thrown: read access violation.
this->native_widget_ was nullptr.

Is this a bug in CEF (to check web_contents_->native_widget_ pointer before calling ::SetFocus(HWNDForWidget(window_widget_)), or is there something different we can do in our code to avoid this exception?

Code: Select all
void CefBrowserPlatformDelegateNativeWin::SetFocus(bool setFocus) {
  if (!setFocus)
    return;

  if (web_contents_) {
    // Give logical focus to the RenderWidgetHostViewAura in the views
    // hierarchy. This does not change the native keyboard focus.
    web_contents_->Focus();
  }

  if (window_widget_) {
    // Give native focus to the DesktopWindowTreeHostWin associated with the
    // root window.
    //
    // The DesktopWindowTreeHostWin HandleNativeFocus/HandleNativeBlur methods
    // are called in response to WM_SETFOCUS/WM_KILLFOCUS respectively. The
    // implementation has been patched to call HandleActivationChanged which
    // results in the following behaviors:
    // 1. Update focus/activation state of the aura::Window indirectly via
    //    wm::FocusController. This allows focus-related behaviors (e.g. focus
    //    rings, flashing caret, onFocus/onBlur JS events, etc.) to work as
    //    expected (see issue #1677).
    // 2. Update focus state of the ui::InputMethod. If this does not occur
    //    then InputMethodBase::GetTextInputClient will return NULL and
    //    InputMethodWin::OnChar will fail to sent character events to the
    //    renderer (see issue #1700).
    //
    // This differs from activation in Chrome which is handled via
    // HWNDMessageHandler::PostProcessActivateMessage (Widget::Show indirectly
    // calls HWNDMessageHandler::Activate which calls ::SetForegroundWindow
    // resulting in a WM_ACTIVATE message being sent to the window). The Chrome
    // code path doesn't work for CEF because IsTopLevelWindow in
    // hwnd_message_handler.cc will return false and consequently
    // HWNDMessageHandler::PostProcessActivateMessage will not be called.
    //
    // Activation events are usually reserved for the top-level window so
    // triggering activation based on focus events may be incorrect in some
    // circumstances. Revisit this implementation if additional problems are
    // discovered.
    ::SetFocus(HWNDForWidget(window_widget_));
   



Call Stack:

Code: Select all
    libcef.dll!views::Widget::GetNativeWindow() Line 483   C++
>   libcef.dll!views::HWNDForWidget(const views::Widget * widget) Line 22   C++
    libcef.dll!CefBrowserPlatformDelegateNativeWin::SetFocus(bool setFocus) Line 312   C++
    libcef.dll!AlloyBrowserHostImpl::OnSetFocus(<unnamed-tag> source) Line 819   C++
    libcef.dll!AlloyBrowserHostImpl::SetFocusInternal(bool focus) Line 368   C++
    [Inline Frame] libcef.dll!base::internal::FunctorTraits<void (CefMenuModelImpl::*)(bool) __attribute__((thiscall)),void>::Invoke(void(CefMenuModelImpl::*)(bool) method, scoped_refptr<CefMenuModelImpl> && receiver_ptr, bool && args) Line 533   C++
    [Inline Frame] libcef.dll!base::internal::InvokeHelper<0,void>::MakeItSo(void(CefMenuModelImpl::*)(bool) && functor, scoped_refptr<CefMenuModelImpl> && args, bool && args) Line 708   C++
    [Inline Frame] libcef.dll!base::internal::Invoker<base::internal::BindState<void (CefMenuModelImpl::*)(bool) __attribute__((thiscall)),scoped_refptr<CefMenuModelImpl>,bool>,void ()>::RunImpl(void(CefMenuModelImpl::*)(bool) && functor, std::__1::tuple<scoped_refptr<CefMenuModelImpl>,bool> && bound, std::__1::integer_sequence<unsigned int,0,1>) Line 781   C++
    libcef.dll!base::internal::Invoker<base::internal::BindState<void (CefMenuModelImpl::*)(bool) __attribute__((thiscall)),scoped_refptr<CefMenuModelImpl>,bool>,void ()>::RunOnce(base::internal::BindStateBase * base) Line 754   C++
    [Inline Frame] libcef.dll!base::OnceCallback<void ()>::Run() Line 142   C++
    libcef.dll!base::TaskAnnotator::RunTaskImpl(base::PendingTask & pending_task) Line 157   C++
    [Inline Frame] libcef.dll!base::TaskAnnotator::RunTask(perfetto::StaticString event_name, base::PendingTask & pending_task, base::sequence_manager::internal::ThreadControllerWithMessagePumpImpl::DoWorkImpl::<lambda_0> && args) Line 73   C++
    libcef.dll!base::sequence_manager::internal::ThreadControllerWithMessagePumpImpl::DoWorkImpl(base::sequence_manager::LazyNow * continuation_lazy_now) Line 356   C++
    libcef.dll!base::sequence_manager::internal::ThreadControllerWithMessagePumpImpl::DoWork() Line 267   C++
    libcef.dll!base::MessagePumpForUI::DoRunLoop() Line 221   C++
    libcef.dll!base::MessagePumpWin::Run(base::MessagePump::Delegate * delegate) Line 79   C++
    libcef.dll!base::sequence_manager::internal::ThreadControllerWithMessagePumpImpl::Run(bool application_tasks_allowed, base::TimeDelta timeout) Line 471   C++
    libcef.dll!base::RunLoop::Run(const base::Location & location) Line 142   C++
    libcef.dll!base::RunLoop::RunUntilIdle() Line 151   C++
    libcef.dll!CefDoMessageLoopWork() Line 255   C++
    ceraexe0.exe!CefDoMessageLoopWork() Line 129   C++
    ceraexe0.exe!CCerApp::OnIdle(long lCount) Line 425   C++



Thank you.
ctrebs
Newbie
 
Posts: 7
Joined: Wed Jun 22, 2022 4:56 pm

Re: Usage of m_cefBrowser->GetHost()->SetFocus

Postby magreenblatt » Wed Jul 20, 2022 3:33 pm

What is your application doing when it gets this crash? For example, have you just closed the browser or parent window? Are the browser and parent window handles both valid (IsWindow returns true?)
magreenblatt
Site Admin
 
Posts: 12408
Joined: Fri May 29, 2009 6:57 pm

Re: Usage of m_cefBrowser->GetHost()->SetFocus

Postby ctrebs » Fri Jul 22, 2022 10:30 am

The crash happens sporadically, but yes I do think it's related to closing browser (and parent) windows. The last time I saw it happen, I had several child windows opened (each containing a browser) and clicked 'close all windows' in the app which programmatically closes all child windows (causing each child window to close it's browser). During this close all process, SetFocus may be called because when the active child window is closed another child window that is still open will get activated (causing it to call it's browser's SetFocus).

I can add IsWindow check's to ensure that both the browser and it's parent window are valid before calling browser SetFocus to see if that helps.

However, it seems browser->SetFocus cues a message (and the browser and parent window may be valid windows at that time), but by the time the message is getting processed (when we call CefDoMessageLoopWork) the browser (and parent) could have been destroyed causing the exception in CefBrowserPlatformDelegateNativeWin::SetFocus
ctrebs
Newbie
 
Posts: 7
Joined: Wed Jun 22, 2022 4:56 pm

Re: Usage of m_cefBrowser->GetHost()->SetFocus

Postby magreenblatt » Fri Jul 22, 2022 10:54 am

ctrebs wrote:However, it seems browser->SetFocus cues a message (and the browser and parent window may be valid windows at that time), but by the time the message is getting processed (when we call CefDoMessageLoopWork) the browser (and parent) could have been destroyed causing the exception in CefBrowserPlatformDelegateNativeWin::SetFocus

Agreed. However, since you are using an old/unsupported version (97), you will either need a workaround for the problem or build CEF yourself to fix.
magreenblatt
Site Admin
 
Posts: 12408
Joined: Fri May 29, 2009 6:57 pm

Re: Usage of m_cefBrowser->GetHost()->SetFocus

Postby ctrebs » Fri Jul 22, 2022 4:00 pm

Actually we were just starting to test with version 97. We plan to get onto the latest stable version (103) before testing further and putting into production. What is the process for requesting this fix on a supported release? (I will also explore your suggestions of workaround or build CEF ourselves with the fix)

Thank you for your time and assistance!
ctrebs
Newbie
 
Posts: 7
Joined: Wed Jun 22, 2022 4:56 pm

Re: Usage of m_cefBrowser->GetHost()->SetFocus

Postby magreenblatt » Fri Jul 22, 2022 4:09 pm

What is the process for requesting this fix on a supported release?

First test if the problem reproduces with a supported version. If so, please add a bug in the issue tracker. You're also welcome to fix the issue and submit a PR against current master.
magreenblatt
Site Admin
 
Posts: 12408
Joined: Fri May 29, 2009 6:57 pm

Re: Usage of m_cefBrowser->GetHost()->SetFocus

Postby ctrebs » Fri Jul 22, 2022 7:55 pm

I put in a workaround to process the message from browser->SetFocus(true) right away and that avoids the exception. Will try the original code in later release when we get there.. thanks again.

Code: Select all
         if ((m_cefBrowser) && (::IsWindow(m_cefBrowser->GetHost()->GetWindowHandle())) && (::IsWindow(this->m_hWnd)))
         {
            if (CefCurrentlyOn(TID_UI))
            {
               m_cefBrowser->GetHost()->SetFocus(true);
               CefDoMessageLoopWork();
               Sleep(40);
            }
         }
ctrebs
Newbie
 
Posts: 7
Joined: Wed Jun 22, 2022 4:56 pm

Re: Usage of m_cefBrowser->GetHost()->SetFocus

Postby magreenblatt » Sun Jul 24, 2022 11:07 am

magreenblatt wrote:
What is the process for requesting this fix on a supported release?

First test if the problem reproduces with a supported version. If so, please add a bug in the issue tracker. You're also welcome to fix the issue and submit a PR against current master.

Could be https://bitbucket.org/chromiumembedded/ ... o-disposal
magreenblatt
Site Admin
 
Posts: 12408
Joined: Fri May 29, 2009 6:57 pm

Re: Usage of m_cefBrowser->GetHost()->SetFocus

Postby ndesktop » Sun Jul 24, 2022 11:53 pm

i have seen this several times, especially when debugging and focus jumped back and forth due to VS debugger.
It seems platform native window is destroyed and SetFocus causes a call to a GetNativeWindow which crashes.
ndesktop
Master
 
Posts: 756
Joined: Thu Dec 03, 2015 10:10 am

Re: Usage of m_cefBrowser->GetHost()->SetFocus

Postby ctrebs » Thu Aug 18, 2022 8:38 am

I saw the sporadic exceptions in SetFocus were fixed recently in CEF version 104. I previously stated that I had a workaround solution (when I was using CEF version 99), but with further testing the exception still happened. Thank you for the assistance and for fixing the issue in the latest CEF version!
ctrebs
Newbie
 
Posts: 7
Joined: Wed Jun 22, 2022 4:56 pm


Return to Support Forum

Who is online

Users browsing this forum: Google [Bot] and 76 guests