MicrosoftEdge / MicrosoftEdge/WebView2Feedback

Infinite loop tabbing focus out of the webview if there are no other WS_TABSTOP windows and the document has no tabstop elements

Open
#1,380 1 comment 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

bug priority-low tracked
Dominant language
PowerShell
Stars
526
Forks
67
PR merge metrics
No merged PRs in 30d

Description

Description
This is 100% repro on my project with a specific page, but I haven't been able to construct a standalone repro with about:blank. Hopefully there's enough information here to figure out what's going on, but if not I can keep trying.

There seems to be a feedback loop in the MoveFocusRequested event if there's not a tabstop in the document or in a sibling of the parent window. This repros whether or not I call add_MoveFocusRequested, but that's where I was able to insert tracepoints to see what was happening in the CPU spike.

Version
SDK: 1.0.774.44
Runtime: EdgeWebview, 91.0.864.41
Framework: Win32
OS: Win10

Repro Steps

  1. Create a top-level window with WS_OVERLAPPEDWINDOW.
  2. Create a child window with WS_CHILD | WS_TABSTOP to be the parent of the webview.
  3. Create a webview with the child window (container) as the parent.
  4. Call add_MoveFocusRequested to register a callback.
  5. Set a tracepoint in the MoveFocusRequested callback to output the callstack and the reason.
  6. Navigate to a page with no tabstops. about:blank seems like it should repro, but it doesn't. I'm not sure different about the page I'm using, but it doesn't seem to have any tabstops.
  7. Click on the body of the document to put focus in the webview.
  8. Press the Tab key.

Expected:

There should be a single MoveFocusRequested notification, and focus should end up on the webview by default if put_Handled(true) is not called, since there are no other WS_TABSTOP windows. If put_Handled(true) is called, it should behave the same, but it should leave focus alone (still in the webview by default) because the host has already put focus where it wants to go.

Actual:

Infinite loop moving focus to next, previous, next, previous, ..., and one of the CPU cores is pegged. The app UI is non-responsive, but any animated elements on the page keep running in the separate webview processes.

The first trace is from a WM_SETFOCUS handler on the top-level window, which called MoveFocus on the webview, before pressing Tab. After pressing Tab, there were no more calls to change the focus of the webview.

If I add a WM_SETFOCUS handler to the child/container window, I also see it calling MoveFocus in between each MoveFocusRequested event, indicating that the webview is trying to set focus to its parent as part of the default handling. But when I comment that out and let it do whatever it wants with the focus, it still gets stuck in this loop.

SetFocus: None (0x00000000) 	WebHost.dll!WebHost::Details::WebViewInstance::SetFocus
	sample.exe!WndProc
	user32.dll!UserCallWinProcCheckWow
	user32.dll!DispatchClientMessage
	user32.dll!__fnDWORD
	ntdll.dll!KiUserCallbackDispatch
	win32u.dll!ZwUserMessageCall
	user32.dll!RealDefWindowProcWorker
	[Inline Frame] user32.dll!RealDefWindowProcW
	user32.dll!DefWindowProcW
	sample.exe!WndProc
	user32.dll!UserCallWinProcCheckWow
	user32.dll!DispatchClientMessage
	user32.dll!__fnDWORD
	ntdll.dll!KiUserCallbackDispatch
	win32u.dll!ZwUserGetMessage
	user32.dll!GetMessageW
	sample.exe!wWinMain
	sample.exe!invoke_main
	sample.exe!__scrt_common_main_seh
	sample.exe!__scrt_common_main
	sample.exe!wWinMainCRTStartup
	kernel32.dll!BaseThreadInitThunk
	ntdll.dll!RtlUserThreadStart
	
MoveFocusRequested: COREWEBVIEW2_MOVE_FOCUS_REASON_NEXT (0x00000001) 	WebHost.dll!WebHost::Details::WebViewInstance::AddMoveFocusRequested::__l2::<lambda>
	WebHost.dll!Microsoft::WRL::Details::DelegateArgTraits<long (__cdecl ICoreWebView2MoveFocusRequestedEventHandler::*)(ICoreWebView2Controller *,ICoreWebView2MoveFocusRequestedEventArgs *)>::DelegateInvokeHelper<ICoreWebView2MoveFocusRequestedEventHandler,long <lambda>(ICoreWebView2Controller *, ICoreWebView2MoveFocusRequestedEventArgs *),1,ICoreWebView2Controller *,ICoreWebView2MoveFocusRequestedEventArgs *>::Invoke
	[Inline Frame] EmbeddedBrowserWebView.dll!EventSource<ICoreWebView2MoveFocusRequestedEventHandler>::InvokeAll
	EmbeddedBrowserWebView.dll!embedded_browser_webview_current::EmbeddedBrowserWebViewWindow::OnMoveFocusRequested
	EmbeddedBrowserWebView.dll!embedded_browser::mojom::EmbeddedBrowserClientStubDispatch::Accept
	[Inline Frame] EmbeddedBrowserWebView.dll!mojo::InterfaceEndpointClient::HandleValidatedMessage
	EmbeddedBrowserWebView.dll!mojo::InterfaceEndpointClient::HandleIncomingMessageThunk::Accept
	EmbeddedBrowserWebView.dll!mojo::MessageDispatcher::Accept
	[Inline Frame] EmbeddedBrowserWebView.dll!mojo::InterfaceEndpointClient::HandleIncomingMessage
	[Inline Frame] EmbeddedBrowserWebView.dll!mojo::internal::MultiplexRouter::ProcessIncomingMessage
	EmbeddedBrowserWebView.dll!mojo::internal::MultiplexRouter::Accept
	EmbeddedBrowserWebView.dll!mojo::MessageDispatcher::Accept
	[Inline Frame] EmbeddedBrowserWebView.dll!mojo::Connector::DispatchMessageW
	[Inline Frame] EmbeddedBrowserWebView.dll!mojo::Connector::ReadAllAvailableMessages
	[Inline Frame] EmbeddedBrowserWebView.dll!mojo::Connector::OnHandleReadyInternal
	[Inline Frame] EmbeddedBrowserWebView.dll!mojo::Connector::OnWatcherHandleReady
	[Inline Frame] EmbeddedBrowserWebView.dll!base::internal::FunctorTraits<void (mojo::Connector::*)(unsigned int),void>::Invoke
	[Inline Frame] EmbeddedBrowserWebView.dll!base::internal::InvokeHelper<0,void>::MakeItSo
	[Inline Frame] EmbeddedBrowserWebView.dll!base::internal::Invoker<base::internal::BindState<void (mojo::Connector::*)(unsigned int),base::internal::UnretainedWrapper<mojo::Connector>>,void (unsigned int)>::RunImpl
	[Inline Frame] EmbeddedBrowserWebView.dll!base::internal::Invoker<base::internal::BindState<void (mojo::Connector::*)(unsigned int),base::internal::UnretainedWrapper<mojo::Connector>>,void (unsigned int)>::Run
	[Inline Frame] EmbeddedBrowserWebView.dll!base::RepeatingCallback<void (unsigned int)>::Run
	[Inline Frame] EmbeddedBrowserWebView.dll!mojo::SimpleWatcher::DiscardReadyState
	[Inline Frame] EmbeddedBrowserWebView.dll!base::internal::FunctorTraits<void (*)(const base::RepeatingCallback<void (unsigned int)> &, unsigned int, const mojo::HandleSignalsState &),void>::Invoke
	[Inline Frame] EmbeddedBrowserWebView.dll!base::internal::InvokeHelper<0,void>::MakeItSo
	[Inline Frame] EmbeddedBrowserWebView.dll!base::internal::Invoker<base::internal::BindState<void (*)(const base::RepeatingCallback<void (unsigned int)> &, unsigned int, const mojo::HandleSignalsState &),base::RepeatingCallback<void (unsigned int)>>,void (unsigned int, const mojo::HandleSignalsState &)>::RunImpl
	EmbeddedBrowserWebView.dll!base::internal::Invoker<base::internal::BindState<void (*)(const base::RepeatingCallback<void (unsigned int)> &, unsigned int, const mojo::HandleSignalsState &),base::RepeatingCallback<void (unsigned int)>>,void (unsigned int, const mojo::HandleSignalsState &)>::Run
	[Inline Frame] EmbeddedBrowserWebView.dll!base::RepeatingCallback<void (unsigned int, const mojo::HandleSignalsState &)>::Run
	[Inline Frame] EmbeddedBrowserWebView.dll!mojo::SimpleWatcher::OnHandleReady
	[Inline Frame] EmbeddedBrowserWebView.dll!base::internal::FunctorTraits<void (mojo::SimpleWatcher::*)(int, unsigned int, const mojo::HandleSignalsState &),void>::Invoke
	[Inline Frame] EmbeddedBrowserWebView.dll!base::internal::InvokeHelper<1,void>::MakeItSo
	[Inline Frame] EmbeddedBrowserWebView.dll!base::internal::Invoker<base::internal::BindState<void (mojo::SimpleWatcher::*)(int, unsigned int, const mojo::HandleSignalsState &),base::WeakPtr<mojo::SimpleWatcher>,int,unsigned int,mojo::HandleSignalsState>,void ()>::RunImpl
	EmbeddedBrowserWebView.dll!base::internal::Invoker<base::internal::BindState<void (mojo::SimpleWatcher::*)(int, unsigned int, const mojo::HandleSignalsState &),base::WeakPtr<mojo::SimpleWatcher>,int,unsigned int,mojo::HandleSignalsState>,void ()>::RunOnce
	[Inline Frame] EmbeddedBrowserWebView.dll!base::OnceCallback<void ()>::Run
	EmbeddedBrowserWebView.dll!base::TaskAnnotator::RunTask
	[Inline Frame] EmbeddedBrowserWebView.dll!embedded_browser_webview::internal::AppTaskRunner::DoWork
	EmbeddedBrowserWebView.dll!embedded_browser_webview::internal::AppTaskRunner::MessageCallback
	[Inline Frame] EmbeddedBrowserWebView.dll!base::RepeatingCallback<bool (unsigned int, unsigned long long, long long, long long *)>::Run
	EmbeddedBrowserWebView.dll!base::win::MessageWindow::WindowProc
	EmbeddedBrowserWebView.dll!base::win::WrappedWindowProc<&base::win::MessageWindow::WindowProc>
	user32.dll!UserCallWinProcCheckWow
	user32.dll!DispatchMessageWorker
	sample.exe!wWinMain
	sample.exe!invoke_main
	sample.exe!__scrt_common_main_seh
	sample.exe!__scrt_common_main
	sample.exe!wWinMainCRTStartup
	kernel32.dll!BaseThreadInitThunk
	ntdll.dll!RtlUserThreadStart
	
MoveFocusRequested: COREWEBVIEW2_MOVE_FOCUS_REASON_PREVIOUS (0x00000002) 	WebHost.dll!WebHost::Details::WebViewInstance::AddMoveFocusRequested::__l2::<lambda>
	WebHost.dll!Microsoft::WRL::Details::DelegateArgTraits<long (__cdecl ICoreWebView2MoveFocusRequestedEventHandler::*)(ICoreWebView2Controller *,ICoreWebView2MoveFocusRequestedEventArgs *)>::DelegateInvokeHelper<ICoreWebView2MoveFocusRequestedEventHandler,long <lambda>(ICoreWebView2Controller *, ICoreWebView2MoveFocusRequestedEventArgs *),1,ICoreWebView2Controller *,ICoreWebView2MoveFocusRequestedEventArgs *>::Invoke
	[Inline Frame] EmbeddedBrowserWebView.dll!EventSource<ICoreWebView2MoveFocusRequestedEventHandler>::InvokeAll
	EmbeddedBrowserWebView.dll!embedded_browser_webview_current::EmbeddedBrowserWebViewWindow::OnMoveFocusRequested
	EmbeddedBrowserWebView.dll!embedded_browser::mojom::EmbeddedBrowserClientStubDispatch::Accept
	[Inline Frame] EmbeddedBrowserWebView.dll!mojo::InterfaceEndpointClient::HandleValidatedMessage
	EmbeddedBrowserWebView.dll!mojo::InterfaceEndpointClient::HandleIncomingMessageThunk::Accept
	EmbeddedBrowserWebView.dll!mojo::MessageDispatcher::Accept
	[Inline Frame] EmbeddedBrowserWebView.dll!mojo::InterfaceEndpointClient::HandleIncomingMessage
	[Inline Frame] EmbeddedBrowserWebView.dll!mojo::internal::MultiplexRouter::ProcessIncomingMessage
	EmbeddedBrowserWebView.dll!mojo::internal::MultiplexRouter::Accept
	EmbeddedBrowserWebView.dll!mojo::MessageDispatcher::Accept
	[Inline Frame] EmbeddedBrowserWebView.dll!mojo::Connector::DispatchMessageW
	[Inline Frame] EmbeddedBrowserWebView.dll!mojo::Connector::ReadAllAvailableMessages
	EmbeddedBrowserWebView.dll!mojo::Connector::CallDispatchNextMessageFromPipe
	[Inline Frame] EmbeddedBrowserWebView.dll!base::OnceCallback<void ()>::Run
	EmbeddedBrowserWebView.dll!base::TaskAnnotator::RunTask
	[Inline Frame] EmbeddedBrowserWebView.dll!embedded_browser_webview::internal::AppTaskRunner::DoWork
	EmbeddedBrowserWebView.dll!embedded_browser_webview::internal::AppTaskRunner::MessageCallback
	[Inline Frame] EmbeddedBrowserWebView.dll!base::RepeatingCallback<bool (unsigned int, unsigned long long, long long, long long *)>::Run
	EmbeddedBrowserWebView.dll!base::win::MessageWindow::WindowProc
	EmbeddedBrowserWebView.dll!base::win::WrappedWindowProc<&base::win::MessageWindow::WindowProc>
	user32.dll!UserCallWinProcCheckWow
	user32.dll!DispatchMessageWorker
	sample.exe!wWinMain
	sample.exe!invoke_main
	sample.exe!__scrt_common_main_seh
	sample.exe!__scrt_common_main
	sample.exe!wWinMainCRTStartup
	kernel32.dll!BaseThreadInitThunk
	ntdll.dll!RtlUserThreadStart
	
MoveFocusRequested: COREWEBVIEW2_MOVE_FOCUS_REASON_NEXT (0x00000001) 	WebHost.dll!WebHost::Details::WebViewInstance::AddMoveFocusRequested::__l2::<lambda>
	WebHost.dll!Microsoft::WRL::Details::DelegateArgTraits<long (__cdecl ICoreWebView2MoveFocusRequestedEventHandler::*)(ICoreWebView2Controller *,ICoreWebView2MoveFocusRequestedEventArgs *)>::DelegateInvokeHelper<ICoreWebView2MoveFocusRequestedEventHandler,long <lambda>(ICoreWebView2Controller *, ICoreWebView2MoveFocusRequestedEventArgs *),1,ICoreWebView2Controller *,ICoreWebView2MoveFocusRequestedEventArgs *>::Invoke
	[Inline Frame] EmbeddedBrowserWebView.dll!EventSource<ICoreWebView2MoveFocusRequestedEventHandler>::InvokeAll
	EmbeddedBrowserWebView.dll!embedded_browser_webview_current::EmbeddedBrowserWebViewWindow::OnMoveFocusRequested
	EmbeddedBrowserWebView.dll!embedded_browser::mojom::EmbeddedBrowserClientStubDispatch::Accept
	[Inline Frame] EmbeddedBrowserWebView.dll!mojo::InterfaceEndpointClient::HandleValidatedMessage
	EmbeddedBrowserWebView.dll!mojo::InterfaceEndpointClient::HandleIncomingMessageThunk::Accept
	EmbeddedBrowserWebView.dll!mojo::MessageDispatcher::Accept
	[Inline Frame] EmbeddedBrowserWebView.dll!mojo::InterfaceEndpointClient::HandleIncomingMessage
	[Inline Frame] EmbeddedBrowserWebView.dll!mojo::internal::MultiplexRouter::ProcessIncomingMessage
	EmbeddedBrowserWebView.dll!mojo::internal::MultiplexRouter::Accept
	EmbeddedBrowserWebView.dll!mojo::MessageDispatcher::Accept
	[Inline Frame] EmbeddedBrowserWebView.dll!mojo::Connector::DispatchMessageW
	[Inline Frame] EmbeddedBrowserWebView.dll!mojo::Connector::ReadAllAvailableMessages
	EmbeddedBrowserWebView.dll!mojo::Connector::CallDispatchNextMessageFromPipe
	[Inline Frame] EmbeddedBrowserWebView.dll!base::OnceCallback<void ()>::Run
	EmbeddedBrowserWebView.dll!base::TaskAnnotator::RunTask
	[Inline Frame] EmbeddedBrowserWebView.dll!embedded_browser_webview::internal::AppTaskRunner::DoWork
	EmbeddedBrowserWebView.dll!embedded_browser_webview::internal::AppTaskRunner::MessageCallback
	[Inline Frame] EmbeddedBrowserWebView.dll!base::RepeatingCallback<bool (unsigned int, unsigned long long, long long, long long *)>::Run
	EmbeddedBrowserWebView.dll!base::win::MessageWindow::WindowProc
	EmbeddedBrowserWebView.dll!base::win::WrappedWindowProc<&base::win::MessageWindow::WindowProc>
	user32.dll!UserCallWinProcCheckWow
	user32.dll!DispatchMessageWorker
	sample.exe!wWinMain
	sample.exe!invoke_main
	sample.exe!__scrt_common_main_seh
	sample.exe!__scrt_common_main
	sample.exe!wWinMainCRTStartup
	kernel32.dll!BaseThreadInitThunk
	ntdll.dll!RtlUserThreadStart

...

Screenshots

Additional context

AB#33685721

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

The issue names the MoveFocusRequested callback, WM_SETFOCUS handlers, and MoveFocus calls but no repository files or tests. Begin with the Win32 repro steps and trace the alternating NEXT/PREVIOUS focus notifications. Done means Tab produces one notification and focus remains stable without pegging a CPU core.

Written by the indexing model from the issue text.

Assessment

Domain
desktop-dev
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
28/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.