cefsharp / cefsharp/CefSharp

[invalid] custom popup hosting / lifespan with Wpf.HwndHost causes crash on popup with ChromeStyle

Offen
#4,980 2 Kommentare 0 Reaktionen 0 zugewiesene Personen Auf GitHub ansehen
Vorherrschende Sprache
C#
Sterne
10.3k
Forks
2.9k
Ø Merge
5 T. 22 Std.
Gemergte PRs (30 T.)
4

Beschreibung

### Is there an existing issue for this?

- [X] I have searched both open/closed issues, no issue already exists.

### CefSharp Version

130

### Operating System

Windows 10

### Architecture

x64

### .Net Version

.net 6

### Implementation

WPF

### Reproduction Steps

We don't quite have HwndHost integrated into the main CefSharp sample yet but if we did then uncommenting https://github.com/cefsharp/CefSharp/blob/master/CefSharp.Wpf.Example/Views/BrowserTabView.xaml.cs#L129-L183 would result in the crash (note if trying to repro with external HwndHost need to add the experimental handlers to the inclusion).

Once you do so just open a new popup (ie target= _blank) and it will crash.

### Expected behavior

Not Crash

### Actual behavior

Crashes

### Regression?

Doubt it

### Known Workarounds

Unable to find any

### Does this problem also occur in the CEF Sample Application

No

### Other information

This might be a bug in CEF based on the cef code comments but I can't reproduce it so we might be calling down some wrong path. It doesn't happen with WPF (non HwndHost) (or seemingly WinForms) but if the CEF comment is right the flow would only be an issue with chrome style not alloy style windows. See below for more details.

The error occurs because the 'pending popup' var set to empty and then it trying to copy properties from that.

src is: 0x00000000000000a8
(this seems to be a CEF constant for empty for pending popup)
```cpp
so: target->windowless_frame_rate = src->windowless_frame_rate; throws a read error
> libcef.dll!CefBrowserSettingsTraits::set(const _cef_browser_settings_t * src, _cef_browser_settings_t * target, bool copy) Line 500 C++
[Inline Frame] libcef.dll!CefStructBase::Set(const _cef_browser_settings_t & source, bool copy) Line 108 C++
[Inline Frame] libcef.dll!CefStructBase::operator=(const _cef_browser_settings_t & s) Line 116 C++
[Inline Frame] libcef.dll!CefStructBase::operator=(const CefStructBase & s) Line 112 C++
libcef.dll!CefBrowserInfoManager::WebContentsCreated(const GURL & target_url, const content::GlobalRenderFrameHostId & opener_global_id, CefStructBase & settings, scoped_refptr & client, std::__Cr::unique_ptr> & platform_delegate, scoped_refptr & extra_info, content::WebContents * new_contents) Line 266 C++
libcef.dll!ChromeBrowserDelegate::WebContentsCreated(content::WebContents * source_contents, int opener_render_process_id, int opener_render_frame_id, const std::__Cr::basic_string,std::__Cr::allocator> & frame_name, const GURL & target_url, content::WebContents * new_contents) Line 508 C++
libcef.dll!content::WebContentsImpl::CreateNewWindow(content::RenderFrameHostImpl * opener, const content::mojom::CreateNewWindowParams & params, bool is_new_browsing_instance, bool has_user_gesture, content::SessionStorageNamespace * session_storage_namespace) Line 4862 C++
libcef.dll!content::RenderFrameHostImpl::CreateNewWindow(mojo::StructPtr params, base::OnceCallback)> callback) Line 9144 C++
libcef.dll!content::mojom::FrameHostStubDispatch::AcceptWithResponder(content::mojom::FrameHost * impl, mojo::Message * message, std::__Cr::unique_ptr> responder) Line 5736 C++
libcef.dll!content::mojom::FrameHostStub>::AcceptWithResponder(mojo::Message * message, std::__Cr::unique_ptr> responder) Line 860 C++
[Inline Frame] libcef.dll!mojo::InterfaceEndpointClient::HandleValidatedMessage(mojo::Message * message) Line 1005 C++
libcef.dll!mojo::InterfaceEndpointClient::HandleIncomingMessageThunk::Accept(mojo::Message * message) Line 371 C++
libcef.dll!mojo::MessageDispatcher::Accept(mojo::Message * message) Line 48 C++
libcef.dll!mojo::InterfaceEndpointClient::HandleIncomingMessage(mojo::Message * message) Line 724 C++
libcef.dll!IPC::ChannelAssociatedGroupController::AcceptSyncMessage(unsigned int interface_id, unsigned int message_id, IPC::`anonymous namespace'::ScopedUrgentMessageNotification scoped_urgent_message_notification) Line 1259 C++
[Inline Frame] libcef.dll!base::internal::DecayedFunctorTraits::Invoke(void(IPC::ChannelAssociatedGroupController::*)(unsigned int, unsigned int, IPC::`anonymous namespace'::ScopedUrgentMessageNotification) method, scoped_refptr && receiver_ptr, unsigned int && args, unsigned int && args, IPC::`anonymous namespace'::ScopedUrgentMessageNotification && args) Line 738 C++
[Inline Frame] libcef.dll!base::internal::InvokeHelper<0,base::internal::FunctorTraits,void,0,1,2,3>::MakeItSo(void(IPC::ChannelAssociatedGroupController::*)(unsigned int, unsigned int, IPC::`anonymous namespace'::ScopedUrgentMessageNotification) && functor, std::__Cr::tuple,unsigned int,unsigned int,IPC::(anonymous namespace)::ScopedUrgentMessageNotification> && bound) Line 930 C++
[Inline Frame] libcef.dll!base::internal::Invoker,base::internal::BindState<1,1,0,void (IPC::ChannelAssociatedGroupController::*)(unsigned int, unsigned int, IPC::(anonymous namespace)::ScopedUrgentMessageNotification),scoped_refptr,unsigned int,unsigned int,IPC::(anonymous namespace)::ScopedUrgentMessageNotification>,void ()>::RunImpl(void(IPC::ChannelAssociatedGroupController::*)(unsigned int, unsigned int, IPC::`anonymous namespace'::ScopedUrgentMessageNotification) && functor, std::__Cr::tuple,unsigned int,unsigned int,IPC::(anonymous namespace)::ScopedUrgentMessageNotification> && bound, std::__Cr::integer_sequence) Line 1067 C++
libcef.dll!base::internal::Invoker,base::internal::BindState<1,1,0,void (IPC::ChannelAssociatedGroupController::*)(unsigned int, unsigned int, IPC::(anonymous namespace)::ScopedUrgentMessageNotification),scoped_refptr,unsigned int,unsigned int,IPC::(anonymous namespace)::ScopedUrgentMessageNotification>,void ()>::RunOnce(base::internal::BindStateBase * base) Line 980 C++
[Inline Frame] libcef.dll!base::OnceCallback::Run() Line 156 C++
libcef.dll!base::TaskAnnotator::RunTaskImpl(base::PendingTask & pending_task) Line 203 C++
[Inline Frame] libcef.dll!base::TaskAnnotator::RunTask(perfetto::StaticString event_name, base::PendingTask & pending_task, base::sequence_manager::internal::ThreadControllerWithMessagePumpImpl::DoWorkImpl:: && args) Line 90 C++
[Inline Frame] libcef.dll!base::sequence_manager::internal::ThreadControllerWithMessagePumpImpl::DoWorkImpl(base::LazyNow * continuation_lazy_now) Line 470 C++
libcef.dll!base::sequence_manager::internal::ThreadControllerWithMessagePumpImpl::DoWork() Line 332 C++
libcef.dll!base::MessagePumpForUI::DoRunLoop() Line 260 C++
libcef.dll!base::MessagePumpWin::Run(base::MessagePump::Delegate * delegate) Line 85 C++
libcef.dll!base::sequence_manager::internal::ThreadControllerWithMessagePumpImpl::Run(bool application_tasks_allowed, base::TimeDelta timeout) Line 643 C++
libcef.dll!base::RunLoop::Run(const base::Location & location) Line 136 C++
libcef.dll!CefMainRunner::RunMessageLoop() Line 198 C++
libcef.dll!CefUIThread::ThreadMain() Line 106 C++
libcef.dll!base::`anonymous namespace'::ThreadFunc(void * params) Line 124 C++
kernel32.dll!00007ffbfa4d7374() Unknown
ntdll.dll!00007ffbfaedcc91() Unknown
```

The may be more telling is the code https://github.com/chromiumembedded/cef/blob/e513077eaca4097e2283cb70bcd72c804a6ee922/libcef/browser/browser_info_manager.cc#L318-L321

where it tries to get the pending popup information. If the comment saying `GET_CUSTOM_WEB_CONTENTS_VIEW` should only be used with alloy style maybe that is why this happens? I doubt this specifically given it also does an alloy style check below on pending_popup so maybe it just means GET_CUSTOM_WEB_CONTENTS_VIEW is ignored if not alloy style. Either way poppendingpopup returns empty. If it does mean GET_CUSTOM_WEB_CONTENTS_VIEW shouldn't be called on chrome style then I figured I should be able to reproduce it with:
```
./cefclient.exe --no-sandbox --lang=en-US --remote-debugging-port=8088 --uncaught-exception-stack-size=10 --use-chrome-style-window --disable-features=EnableHangWatcher --disable-chrome-login-prompt --hide-crash-restore-bubble --enable-unsafe-extension-debugging --enable-experimental-extension-apis --no-proxy-server --cache-path=f:/cache/ --url=https://google.com --use-views
```
and doing the new popup test. This succeeds though both with and without the `--use-default-popup` arg. The [PopPendingPopup](https://github.com/chromiumembedded/cef/blob/e513077eaca4097e2283cb70bcd72c804a6ee922/libcef/browser/browser_info_manager.cc#L668) function does seem to handle chromestyle too.

I tried to repro in WinForms without success as well. I added `CefSharpSettings.RuntimeStyle = CefRuntimeStyle.Chrome;` to program.cs and tried both the normal lifespan handler and setting it equal to `browser.LifeSpanHandler = new WinFormsLifeSpanHandlerEx();` but I am not sure if that is really a full hosted popup. Without HandlerEx new tabs open fine no matter what target is set to or if shift is held on links (everything just opens as new tab). When set to HandlerEx things that should open in new window do nothing (but no crash), but holding control does cause new tabs to open properly on links.

Back to where it does crash I found if you hold control or shift it does not crash when clicking the link with target _blank. Similar to in the non HwndHost WPF version holding control/shift just causes links to open in the same tab. These just don't flow through the lifespan handler for popups.

Beitragsleitfaden

Beitragsleitfaden öffnen

Rechercherichtung

Beginne mit CefSharp.Wpf.Example/Views/BrowserTabView.xaml.cs ungefähr bei den Zeilen 129–183 und reproduziere ein target=_blank-Popup mit Wpf.HwndHost und ChromeStyle. Vergleiche den Popup-Ablauf mit den Verweisen in CEF browser_info_manager.cc und ermittle das relevante Verhalten beim Hosting oder bei der Lebensdauer. Erledigt ist die Aufgabe, wenn das gehostete Popup in diesem Szenario nicht mehr abstürzt.

Vom Indexierungsmodell aus dem Issue-Text verfasst.

Bewertung

Tech-Stack
cpp, csharp
Bereich
desktop
Issue-Typ
Bug
Schwierigkeit
5/5
Geschätzter Aufwand
Über eine Woche
Aktivitätsstatus
Veraltet
Klarheit
Muss geklärt werden
Anfängerfreundlichkeit
20/100

Neue Issues direkt in Ihr Postfach

Eine kurze Übersicht über anfängerfreundliche GitHub-Issues.