From b8b6c794153f86eef1e8c699359417754d758004 Mon Sep 17 00:00:00 2001 From: Masayuki Nakano Date: Thu, 8 Apr 2021 00:11:26 +0000 Subject: [PATCH] Bug 1700004 - Make `FuzzingFunctions::SynthesizeKeyboardEvents` synthesize keyboard events in in-process top window rather than active window r=smaug Currently, it tries to synthesize keyboard events on active window for emulating user input as far as possible. However, in the Fission world, it cannot retrieve active window from a content process for OOP iframe. And current behavior does not allow to emulate synthesizing keyboard events in inactive window which may be caused by 3rd party apps like IME. Therefore, this patch makes it synthesize keyboard events in in-process top window from the caller's global object. If we support synthesizing keyboard events via main process, we can change the behavior better. But for now, this must be enough for the Fuzzing API users. Differential Revision: https://phabricator.services.mozilla.com/D111040 --- dom/base/FuzzingFunctions.cpp | 37 ++++++++++++++++++------------ dom/webidl/FuzzingFunctions.webidl | 15 ++++++------ 2 files changed, 30 insertions(+), 22 deletions(-) diff --git a/dom/base/FuzzingFunctions.cpp b/dom/base/FuzzingFunctions.cpp index aab0a0799a87..26a08ad7c51b 100644 --- a/dom/base/FuzzingFunctions.cpp +++ b/dom/base/FuzzingFunctions.cpp @@ -176,10 +176,9 @@ Modifiers FuzzingFunctions::InactivateModifiers( } /* static */ -void FuzzingFunctions::SynthesizeKeyboardEvents(const GlobalObject&, - const nsAString& aKeyValue, - const KeyboardEventInit& aDict, - ErrorResult& aRv) { +void FuzzingFunctions::SynthesizeKeyboardEvents( + const GlobalObject& aGlobalObject, const nsAString& aKeyValue, + const KeyboardEventInit& aDict, ErrorResult& aRv) { // Prepare keyboard event to synthesize first. uint32_t flags = 0; // Don't modify the given dictionary since caller may want to modify @@ -268,20 +267,28 @@ void FuzzingFunctions::SynthesizeKeyboardEvents(const GlobalObject&, event.mKeyNameIndex, maybeNonStandardLocation); } - // Synthesize keyboard events on focused widget. - nsFocusManager* focusManager = nsFocusManager::GetFocusManager(); - if (NS_WARN_IF(!focusManager)) { + // Synthesize keyboard events in a DOM window which is in-process top one. + // For emulating user input, this is better than dispatching the events in + // the caller's DOM window because this approach can test the path redirecting + // the events to focused subdocument too. However, for now, we cannot + // dispatch it via another process without big changes. Therefore, we should + // use in-process top window instead. If you need to test the path in the + // parent process to, please file a feature request bug. + nsCOMPtr windowInner = + do_QueryInterface(aGlobalObject.GetAsSupports()); + if (!windowInner) { aRv.Throw(NS_ERROR_NOT_AVAILABLE); return; } - nsPIDOMWindowOuter* activeWindow = focusManager->GetActiveWindow(); - if (NS_WARN_IF(!activeWindow)) { - aRv.Throw(NS_ERROR_NOT_AVAILABLE); + nsPIDOMWindowOuter* inProcessTopWindowOuter = + windowInner->GetInProcessScriptableTop(); + if (NS_WARN_IF(!inProcessTopWindowOuter)) { + aRv.Throw(NS_ERROR_FAILURE); return; } - nsIDocShell* docShell = activeWindow->GetDocShell(); + nsIDocShell* docShell = inProcessTopWindowOuter->GetDocShell(); if (NS_WARN_IF(!docShell)) { aRv.Throw(NS_ERROR_FAILURE); return; @@ -299,9 +306,9 @@ void FuzzingFunctions::SynthesizeKeyboardEvents(const GlobalObject&, return; } - nsCOMPtr activeWindowInner = - activeWindow->EnsureInnerWindow(); - if (NS_WARN_IF(!activeWindowInner)) { + nsCOMPtr inProcessTopWindowInner = + inProcessTopWindowOuter->EnsureInnerWindow(); + if (NS_WARN_IF(!inProcessTopWindowInner)) { aRv.Throw(NS_ERROR_FAILURE); return; } @@ -309,7 +316,7 @@ void FuzzingFunctions::SynthesizeKeyboardEvents(const GlobalObject&, RefPtr textInputProcessor = new TextInputProcessor(); bool beganInputTransaction = false; aRv = textInputProcessor->BeginInputTransactionForFuzzing( - activeWindowInner, nullptr, &beganInputTransaction); + inProcessTopWindowInner, nullptr, &beganInputTransaction); if (NS_WARN_IF(aRv.Failed())) { return; } diff --git a/dom/webidl/FuzzingFunctions.webidl b/dom/webidl/FuzzingFunctions.webidl index ddc001386af5..252fed536e0b 100644 --- a/dom/webidl/FuzzingFunctions.webidl +++ b/dom/webidl/FuzzingFunctions.webidl @@ -42,13 +42,14 @@ interface FuzzingFunctions { /** * synthesizeKeyboardEvents() synthesizes a set of "keydown", - * "keypress" (only when it's necessary) and "keyup" events on focused - * widget. This is currently not aware of APZ since this dispatches the - * events into focused PresShell in current process. I.e., dispatched - * events won't be handled by some default action handlers which are only - * in the main process. Note that this does not allow to synthesize - * keyboard events if this is called from a keyboard event or composition - * event listener. + * "keypress" (only when it's necessary) and "keyup" events in top DOM window + * in current process (and the synthesized events will be retargeted to + * focused window/document/element). I.e, this is currently not dispatched + * via the main process if you call this in a content process. Therefore, in + * the case, some default action handlers which are only in the main process + * will never run. Note that this does not allow to synthesize keyboard + * events if this is called from a keyboard event or composition event + * listener. * * @param aKeyValue If you want to synthesize non-printable key * events, you need to set one of key values