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
Nobody has claimed this yet.
- 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
- Create a top-level window with WS_OVERLAPPEDWINDOW.
- Create a child window with WS_CHILD | WS_TABSTOP to be the parent of the webview.
- Create a webview with the child window (container) as the parent.
- Call add_MoveFocusRequested to register a callback.
- Set a tracepoint in the MoveFocusRequested callback to output the callstack and the reason.
- 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.
- Click on the body of the document to put focus in the webview.
- 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
Contributor guide
No contributing guide indexed for this repository
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- 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