/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* vim: set ts=8 sts=2 et sw=2 tw=80: */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
SprintfLiteral(msgbuf, "%s", NS_ConvertUTF16toUTF8(aKeyValue).get()); if (aKeyValue.Length() >= sizeof(msgbuf)) { // Update the end of a truncated message to '...'.
strcpy(&msgbuf[sizeof(msgbuf) - 4], "...");
}
MOZ_CRASH_UNSAFE_PRINTF("%s", msgbuf);
}
if (aModifiers == MODIFIER_NONE) { return MODIFIER_NONE;
}
// We don't want to dispatch modifier key event from here. In strictly // speaking, all necessary modifiers should be activated with dispatching // each modifier key event. However, we cannot keep storing // TextInputProcessor instance for multiple SynthesizeKeyboardEvents() calls. // So, if some callers need to emulate modifier key events, they should do // it by themselves.
uint32_t flags = nsITextInputProcessor::KEY_NON_PRINTABLE_KEY |
nsITextInputProcessor::KEY_DONT_DISPATCH_MODIFIER_KEY_EVENT;
Modifiers activatedModifiers = MODIFIER_NONE;
Modifiers activeModifiers = aTextInputProcessor->GetActiveModifiers(); for (const ModifierKey& kModifierKey : kModifierKeys) { if (!(kModifierKey.mModifier & aModifiers)) { continue; // Not requested modifier.
} if (kModifierKey.mModifier & activeModifiers) { continue; // Already active, do nothing.
}
WidgetKeyboardEvent event(true, eVoidEvent, aWidget); // mKeyCode will be computed by TextInputProcessor automatically.
event.mKeyNameIndex = kModifierKey.mKeyNameIndex;
aRv = aTextInputProcessor->Keydown(event, flags); if (NS_WARN_IF(aRv.Failed())) { return activatedModifiers;
} if (kModifierKey.mLockable) {
aRv = aTextInputProcessor->Keyup(event, flags); if (NS_WARN_IF(aRv.Failed())) { return activatedModifiers;
}
}
activatedModifiers |= kModifierKey.mModifier;
} return activatedModifiers;
}
if (aModifiers == MODIFIER_NONE) { return MODIFIER_NONE;
}
// We don't want to dispatch modifier key event from here. In strictly // speaking, all necessary modifiers should be activated with dispatching // each modifier key event. However, we cannot keep storing // TextInputProcessor instance for multiple SynthesizeKeyboardEvents() calls. // So, if some callers need to emulate modifier key events, they should do // it by themselves.
uint32_t flags = nsITextInputProcessor::KEY_NON_PRINTABLE_KEY |
nsITextInputProcessor::KEY_DONT_DISPATCH_MODIFIER_KEY_EVENT;
Modifiers inactivatedModifiers = MODIFIER_NONE;
Modifiers activeModifiers = aTextInputProcessor->GetActiveModifiers(); for (const ModifierKey& kModifierKey : kModifierKeys) { if (!(kModifierKey.mModifier & aModifiers)) { continue; // Not requested modifier.
} if (kModifierKey.mModifier & activeModifiers) { continue; // Already active, do nothing.
}
WidgetKeyboardEvent event(true, eVoidEvent, aWidget); // mKeyCode will be computed by TextInputProcessor automatically.
event.mKeyNameIndex = kModifierKey.mKeyNameIndex; if (kModifierKey.mLockable) {
aRv = aTextInputProcessor->Keydown(event, flags); if (NS_WARN_IF(aRv.Failed())) { return inactivatedModifiers;
}
}
aRv = aTextInputProcessor->Keyup(event, flags); if (NS_WARN_IF(aRv.Failed())) { return inactivatedModifiers;
}
inactivatedModifiers |= kModifierKey.mModifier;
} return inactivatedModifiers;
}
/* static */ 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 // a part of it and call this with it again.
WidgetKeyboardEvent event(true, eVoidEvent, nullptr);
event.mKeyCode = aDict.mKeyCode;
event.mCharCode = 0; // Ignore.
event.mKeyNameIndex = WidgetKeyboardEvent::GetKeyNameIndex(aKeyValue); if (event.mKeyNameIndex == KEY_NAME_INDEX_USE_STRING) {
event.mKeyValue = aKeyValue;
} // code value should be empty string or one of valid code value.
event.mCodeNameIndex =
aDict.mCode.IsEmpty()
? CODE_NAME_INDEX_UNKNOWN
: WidgetKeyboardEvent::GetCodeNameIndex(aDict.mCode); if (NS_WARN_IF(event.mCodeNameIndex == CODE_NAME_INDEX_USE_STRING)) { // Meaning that the code value is specified but it's not a known code // value. TextInputProcessor does not support synthesizing keyboard // events with unknown code value. So, returns error now.
aRv.Throw(NS_ERROR_INVALID_ARG); return;
}
event.mLocation = aDict.mLocation;
event.mIsRepeat = aDict.mRepeat;
// If we could distinguish whether the caller specified 0 explicitly or // not, we would skip computing the key location when it's specified // explicitly. However, this caller probably won't test tricky keyboard // events, so, it must be enough even though caller cannot set location // to 0.
Maybe<uint32_t> maybeNonStandardLocation; if (!event.mLocation) {
maybeNonStandardLocation = mozilla::Some(event.mLocation);
}
// If the key is a printable key and |.code| and/or |.keyCode| value is // not specified as non-zero explicitly, let's assume that the caller // emulates US-English keyboard's behavior (because otherwise, caller // should set both values. if (event.mKeyNameIndex == KEY_NAME_INDEX_USE_STRING) { if (event.mCodeNameIndex == CODE_NAME_INDEX_UNKNOWN) {
event.mCodeNameIndex =
TextInputProcessor::GuessCodeNameIndexOfPrintableKeyInUSEnglishLayout(
event.mKeyValue, maybeNonStandardLocation);
MOZ_ASSERT(event.mCodeNameIndex != CODE_NAME_INDEX_USE_STRING);
} if (!event.mKeyCode) {
event.mKeyCode =
TextInputProcessor::GuessKeyCodeOfPrintableKeyInUSEnglishLayout(
event.mKeyValue, maybeNonStandardLocation); if (!event.mKeyCode) { // Prevent to recompute keyCode in TextInputProcessor.
flags |= nsITextInputProcessor::KEY_KEEP_KEYCODE_ZERO;
}
}
} // If the key is a non-printable key, we can compute |.code| value of // usual keyboard of the platform. Note that |.keyCode| value for // non-printable key will be computed by TextInputProcessor. So, we need // to take care only |.code| value here. elseif (event.mCodeNameIndex == CODE_NAME_INDEX_UNKNOWN) {
event.mCodeNameIndex =
WidgetKeyboardEvent::ComputeCodeNameIndexFromKeyNameIndex(
event.mKeyNameIndex, maybeNonStandardLocation);
}
// 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<nsPIDOMWindowInner> windowInner =
do_QueryInterface(aGlobalObject.GetAsSupports()); if (!windowInner) {
aRv.Throw(NS_ERROR_NOT_AVAILABLE); return;
}
nsPIDOMWindowOuter* inProcessTopWindowOuter =
windowInner->GetInProcessScriptableTop(); if (NS_WARN_IF(!inProcessTopWindowOuter)) {
aRv.Throw(NS_ERROR_FAILURE); return;
}
nsIDocShell* docShell = inProcessTopWindowOuter->GetDocShell(); if (NS_WARN_IF(!docShell)) {
aRv.Throw(NS_ERROR_FAILURE); return;
}
RefPtr<nsPresContext> presContext = docShell->GetPresContext(); if (NS_WARN_IF(!presContext)) {
aRv.Throw(NS_ERROR_FAILURE); return;
}
event.mWidget = presContext->GetRootWidget(); if (NS_WARN_IF(!event.mWidget)) {
aRv.Throw(NS_ERROR_FAILURE); return;
}
nsCOMPtr<nsPIDOMWindowInner> inProcessTopWindowInner =
inProcessTopWindowOuter->EnsureInnerWindow(); if (NS_WARN_IF(!inProcessTopWindowInner)) {
aRv.Throw(NS_ERROR_FAILURE); return;
}
RefPtr<TextInputProcessor> textInputProcessor = new TextInputProcessor(); bool beganInputTransaction = false;
aRv = textInputProcessor->BeginInputTransactionForFuzzing(
inProcessTopWindowInner, nullptr, &beganInputTransaction); if (NS_WARN_IF(aRv.Failed())) { return;
} if (NS_WARN_IF(!beganInputTransaction)) { // This is possible if a keyboard event listener or something tries to // dispatch next keyboard events during dispatching a keyboard event via // TextInputProcessor.
aRv.Throw(NS_ERROR_FAILURE); return;
}
// First, activate necessary modifiers. // MOZ_KnownLive(event.mWidget) is safe because `event` is an instance in // the stack, and `mWidget` is `nsCOMPtr<nsIWidget>`.
Modifiers activatedModifiers = ActivateModifiers(
textInputProcessor, event.mModifiers, MOZ_KnownLive(event.mWidget), aRv); if (NS_WARN_IF(aRv.Failed())) { return;
}
// Then, dispatch keydown and keypress.
aRv = textInputProcessor->Keydown(event, flags); if (NS_WARN_IF(aRv.Failed())) { return;
}
// Then, dispatch keyup.
aRv = textInputProcessor->Keyup(event, flags); if (NS_WARN_IF(aRv.Failed())) { return;
}
// Finally, inactivate some modifiers which are activated by this call. // MOZ_KnownLive(event.mWidget) is safe because `event` is an instance in // the stack, and `mWidget` is `nsCOMPtr<nsIWidget>`.
InactivateModifiers(textInputProcessor, activatedModifiers,
MOZ_KnownLive(event.mWidget), aRv); if (NS_WARN_IF(aRv.Failed())) { return;
}
// Unfortunately, we cannot keep storing modifier state in the // TextInputProcessor since if we store it into a static variable, // we need to take care of resetting it when the caller wants. // However, that makes API more complicated. So, until they need // to want
}
// Ensure the timer is stopped in case we're shutting down the process and // didn't get a chance to spin the event loop long enough.
timer->Cancel();
}
} // namespace mozilla::dom
¤ Dauer der Verarbeitung: 0.16 Sekunden
(vorverarbeitet)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung ist noch experimentell.