Page 1 of 3

How to close one CefBrowserView without closing CefWindow?

PostPosted: Sat Aug 13, 2022 5:50 am
by paveldvlip
I have a tabbed CefWindow and a lot of CefBrowserViews inside. Question: How to close one browser without closing CefWindow? After calling CefBrowserHost::CloseBrowser(false) I get a request to close the window in CefWindowDelegate::CanClose() where I return false since I can't close a window that has other open tabs. After that, the browser continues to work and there is no way to tell it that it can be closed. :shock:

Re: How to close one CefBrowserView without closing CefWindo

PostPosted: Sat Aug 13, 2022 9:15 am
by magreenblatt
Remove the BrowserView from the parent View first and then call CloseBrowser(true)?

Re: How to close one CefBrowserView without closing CefWindo

PostPosted: Sat Aug 13, 2022 10:10 am
by paveldvlip
magreenblatt wrote:Remove the BrowserView from the parent View first and then call CloseBrowser(true)?

I am receiving a message from a tab's close button via the OnButtonPressed() function. Here I am calling CloseBrowser(false). Then in DoClose() I remove the CefBrowserView from the CefWindow and call CloseBrowser(true). This has no effect because OnBeforeClose() is not called and the browser stays alive and continues to send and receive internet traffic. What am I doing wrong?

Re: How to close one CefBrowserView without closing CefWindo

PostPosted: Sat Aug 13, 2022 10:36 am
by magreenblatt
Are you releasing all references to the CefBrowserView and CefBrowser? Are you returning true from DoClose? See also the DoClose documentation: https://github.com/chromiumembedded/cef ... ler.h#L106

Re: How to close one CefBrowserView without closing CefWindo

PostPosted: Sat Aug 13, 2022 11:40 am
by paveldvlip
magreenblatt wrote:Are you releasing all references to the CefBrowserView and CefBrowser? Are you returning true from DoClose? See also the DoClose documentation: https://github.com/chromiumembedded/cef ... ler.h#L106

Yes, I released all references except ClientHandler::m_browser, which is released in OnBeforeClose(), but this function is not called. After the CefBrowserView is removed from the CefWindow, the CanClose() function is not called. The browser disappears from the window, but continues to work in the background. When the application is closed by calling CefShutdown(), errors about incorrect shutdown occur in the console. If I close the window manually before calling CefShutdown(), then the browsers close correctly and there are no errors.

Re: How to close one CefBrowserView without closing CefWindo

PostPosted: Sat Aug 13, 2022 12:00 pm
by paveldvlip
I think the problem is that when calling the CloseBrowser(true) function, it waits for the window to close and the window_destroyed_ flag to be set, exiting immediately without doing anything.
https://bitbucket.org/chromiumembedded/ ... #lines-262
Code: Select all
void AlloyBrowserHostImpl::CloseBrowser(bool force_close) {
  if (CEF_CURRENTLY_ON_UIT()) {
    // Exit early if a close attempt is already pending and this method is
    // called again from somewhere other than WindowDestroyed().
    if (destruction_state_ >= DESTRUCTION_STATE_PENDING &&
        (IsWindowless() || !window_destroyed_)) {
      if (force_close && destruction_state_ == DESTRUCTION_STATE_PENDING) {
        // Upgrade the destruction state.
        destruction_state_ = DESTRUCTION_STATE_ACCEPTED;
      }
      return;
    }

    if (destruction_state_ < DESTRUCTION_STATE_ACCEPTED) {
      destruction_state_ = (force_close ? DESTRUCTION_STATE_ACCEPTED
                                        : DESTRUCTION_STATE_PENDING);
    }

    content::WebContents* contents = web_contents();
    if (contents && contents->NeedToFireBeforeUnloadOrUnloadEvents()) {
      // Will result in a call to BeforeUnloadFired() and, if the close isn't
      // canceled, CloseContents().
      contents->DispatchBeforeUnload(false /* auto_cancel */);
    } else {
      CloseContents(contents);
    }
  } else {
    CEF_POST_TASK(CEF_UIT, base::BindOnce(&AlloyBrowserHostImpl::CloseBrowser,
                                          this, force_close));
  }
}

In this case, there is no way to call the WindowDestroyed() function that sets this flag
Code: Select all
void AlloyBrowserHostImpl::WindowDestroyed() {
  CEF_REQUIRE_UIT();
  DCHECK(!window_destroyed_);
  window_destroyed_ = true;
  CloseBrowser(true);
}

It turns out that it is impossible to close the browser without closing the window!

Re: How to close one CefBrowserView without closing CefWindo

PostPosted: Sat Aug 13, 2022 3:44 pm
by magreenblatt
WindowDestroyed should be called when the underlying Views object is deleted: https://github.com/chromiumembedded/cef ... pl.cc#L182

That would normally happen when the Views hierarchy containing the BrowserView is torn down. If the BrowserView is removed, then it should happen when all references are released. You can debug the code to find out what’s going wrong.

Re: How to close one CefBrowserView without closing CefWindo

PostPosted: Fri Aug 19, 2022 5:41 pm
by paveldvlip
I deleted all references to CefBrowserView, but the browser does not close because it keeps a link to its own CefBrowserView
https://github.com/chromiumembedded/cef ... mpl.cc#L31
Code: Select all
// static
CefRefPtr<CefBrowserView> CefBrowserView::GetForBrowser(
    CefRefPtr<CefBrowser> browser) {
  CEF_REQUIRE_UIT_RETURN(nullptr);

  CefBrowserHostBase* browser_impl =
      static_cast<CefBrowserHostBase*>(browser.get());
  if (browser_impl && browser_impl->is_views_hosted())
    return browser_impl->GetBrowserView();
  return nullptr;
}

Can you provide any working version of the source code where deleting CefBrowserView without closing the entire window causes the browser to close? There are no examples of such use in the documentation or cef/tests. Is there any other way to organize work with several browsers in one window?

Re: How to close one CefBrowserView without closing CefWindo

PostPosted: Fri Aug 19, 2022 6:15 pm
by magreenblatt
I’m not aware of a working example. This is why it needs to be debugged.

Re: How to close one CefBrowserView without closing CefWindo

PostPosted: Sat Aug 20, 2022 6:48 am
by paveldvlip
Debugging step by step does not give anything, since part of the source code is missing, and many functions and subfunctions do not bring any understanding of where and what exactly to look for.

Is it possible to make the WindowDestroyed() function callable directly from the program? This will solve the problem. Moreover, the true value is returned in the DoClose() function.