chromiumembedded / cef

Chromium Embedded Framework (CEF). A simple framework for embedding Chromium-based browsers in other applications.
https://bitbucket.org/chromiumembedded/cef/
Other
3.09k stars 450 forks source link

chrome: cefclient: JavaScript cannot intercept key events that are registered Chrome accelerators #3598

Closed magreenblatt closed 8 months ago

magreenblatt commented 8 months ago

Describe the bug The 'keydown' event listener is not triggered for some keyboard combinations that are also registered as Chrome accelerators.

To Reproduce Steps to reproduce the behavior:

  1. Run cefclient --enable-chrome-runtime
  2. Load an html file with the following contents:
    <html><body><script>
    document.addEventListener('keydown', function (event) {
    if (event.ctrlKey && event.key === 'k') {
    console.log('Got it!');
    event.preventDefault();
    }
    });
    </script></body></html>
  3. Open the DevTools console
  4. Type CTRL+K

Expected behavior The "Got it!" message should display in the Console and the default behavior (Google Search in the Chrome omnibox) should be prevented. Instead, no console message is displayed and Google Search is triggered (including the CefCommandHandler::OnChromeCommand callback).

Versions (please complete the following information):

Additional context The problem does not reproduce with Google Chrome or cefsimple.

magreenblatt commented 8 months ago

With cefsimple --enable-chrome-runtime, Browser::PreHandleKeyboardEvent is called for the key press event:

>   libcef.dll!Browser::PreHandleKeyboardEvent(content::WebContents * source, const content::NativeWebKeyboardEvent & event) Line 1427  C++
    content.dll!content::WebContentsImpl::PreHandleKeyboardEvent(const content::NativeWebKeyboardEvent & event) Line 3612   C++
    content.dll!content::RenderWidgetHostImpl::ForwardKeyboardEventWithCommands(const content::NativeWebKeyboardEvent & key_event, const ui::LatencyInfo & latency, std::__Cr::vector<mojo::InlinedStructPtr<blink::mojom::EditCommand>,std::__Cr::allocator<mojo::InlinedStructPtr<blink::mojom::EditCommand>>> commands, bool * update_event) Line 1806   C++
    content.dll!content::RenderWidgetHostViewAura::ForwardKeyboardEventWithLatencyInfo(const content::NativeWebKeyboardEvent & event, const ui::LatencyInfo & latency, bool * update_event) Line 2784   C++
    content.dll!content::RenderWidgetHostViewEventHandler::OnKeyEvent(ui::KeyEvent * event) Line 274    C++
    content.dll!content::RenderWidgetHostViewAura::OnKeyEvent(ui::KeyEvent * event) Line 2106   C++
    ui_events.dll!ui::EventHandler::OnEvent(ui::Event * event) Line 32  C++

With cefclient --enable-chrome-runtime, FocusManager::ProcessAccelerator is called for the key press event:

>   ui_views.dll!views::FocusManager::ProcessAccelerator(const ui::Accelerator & accelerator) Line 477  C++
    ui_views.dll!views::FocusManager::OnKeyEvent(const ui::KeyEvent & event) Line 113   C++
    ui_views.dll!views::FocusManagerEventHandler::OnKeyEvent(ui::KeyEvent * event) Line 25  C++
    ui_events.dll!ui::EventHandler::OnEvent(ui::Event * event) Line 32  C++

The remainder of the call stack is the same in both cases:

    ui_events.dll!ui::EventHandler::OnEvent(ui::Event * event) Line 32  C++
    ui_events.dll!ui::EventDispatcher::DispatchEvent(ui::EventHandler * handler, ui::Event * event) Line 187    C++
    ui_events.dll!ui::EventDispatcher::DispatchEventToEventHandlers(std::__Cr::vector<ui::EventHandler *,std::__Cr::allocator<ui::EventHandler *>> * list, ui::Event * event) Line 174  C++
    ui_events.dll!ui::EventDispatcher::ProcessEvent(ui::EventTarget * target, ui::Event * event) Line 122   C++
    ui_events.dll!ui::EventDispatcherDelegate::DispatchEventToTarget(ui::EventTarget * target, ui::Event * event) Line 82   C++
    ui_events.dll!ui::EventDispatcherDelegate::DispatchEvent(ui::EventTarget * target, ui::Event * event) Line 54   C++
    ui_events.dll!ui::EventProcessor::OnEventFromSource(ui::Event * event) Line 72  C++
>   ui_aura.dll!aura::WindowTreeHost::DispatchKeyEventPostIME(ui::KeyEvent * event) Line 364    C++
    ui_base_ime.dll!ui::InputMethodBase::DispatchKeyEventPostIME(ui::KeyEvent * event) Line 138 C++
    ui_base_ime_win.dll!ui::InputMethodWinBase::ProcessUnhandledKeyEvent(ui::KeyEvent * event, const std::__Cr::vector<CHROME_MSG,std::__Cr::allocator<CHROME_MSG>> * char_msgs) Line 501   C++
    ui_base_ime_win.dll!ui::InputMethodWinBase::DispatchKeyEvent(ui::KeyEvent * event) Line 237 C++
    ui_aura.dll!aura::WindowEventDispatcher::PreDispatchKeyEvent(aura::Window * target, ui::KeyEvent * event) Line 1084 C++
    ui_aura.dll!aura::WindowEventDispatcher::PreDispatchEvent(ui::EventTarget * target, ui::Event * event) Line 562 C++
    ui_events.dll!ui::EventDispatcherDelegate::DispatchEvent(ui::EventTarget * target, ui::Event * event) Line 50   C++
    ui_events.dll!ui::EventProcessor::OnEventFromSource(ui::Event * event) Line 72  C++
    ui_events.dll!ui::EventSource::DeliverEventToSink(ui::Event * event) Line 119   C++
    ui_events.dll!ui::EventSource::SendEventToSinkFromRewriter(const ui::Event * event, const ui::EventRewriter * rewriter) Line 134    C++
    ui_events.dll!ui::EventSource::SendEventToSink(const ui::Event * event) Line 113    C++
    ui_views.dll!views::DesktopWindowTreeHostWin::HandleKeyEvent(ui::KeyEvent * event) Line 1088    C++
    ui_views.dll!views::HWNDMessageHandler::OnKeyEvent(unsigned int message, unsigned int w_param, long l_param) Line 2174  C++
    ui_views.dll!views::HWNDMessageHandler::_ProcessWindowMessage(HWND__ * hWnd, unsigned int uMsg, unsigned int wParam, long lParam, long & lResult, unsigned long dwMsgMapID) Line 398    C++
    ui_views.dll!views::HWNDMessageHandler::OnWndProc(unsigned int message, unsigned int w_param, long l_param) Line 1264   C++
    ui_gfx.dll!gfx::WindowImpl::WndProc(HWND__ * hwnd, unsigned int message, unsigned int w_param, long l_param) Line 302   C++
    ui_gfx.dll!base::win::WrappedWindowProc<&gfx::WindowImpl::WndProc>(HWND__ * hwnd, unsigned int message, unsigned int wparam, long lparam) Line 74   C++
magreenblatt commented 8 months ago

FocusManager::OnKeyEvent is being called in both cases. |focusedview| is ContentsWebView in both cases. However, in the cefsimple case AcceleratorManager::HasPriorityHandler is returning false and consequently OnKeyEvent is returning early here.

The accelerator is being registered with kNormalPriority in both cases, so it's odd that HasPriorityHandler would return true for cefclient.

magreenblatt commented 8 months ago

Looks like the problem is WebView::SkipDefaultKeyEventProcessing returning false in cefclient due to |allowaccelerators=true|, because we're calling SetPreferAccelerators from ViewsWindow::AddAccelerators in cefclient 🙄